0

I have this Task which fills an observable collection with data from a datatable.

The problem is that when i run this the UI freezes for 1 second at:

Map.Add(mapCollection);

i have tried with no success

Task.Run

The whole code is like this:

private async Task<ObservableCollection<ShiftPageListItemViewModel>> GetMapAsync()
{
    mDbConnect = new DBConnect();

    var ShiftsTab = new DataTable();

    ShiftsTab = await mDbConnect.MapAsync(Date.ToString("yyyy-MM-dd"));

    var Map = new ObservableCollection<ShiftPageListItemViewModel>();


    foreach (DataRow row in ShiftsTab.Rows)
    {
        var mapCollection = new ShiftPageListItemViewModel
        {
            BorderTag = row[0].ToString(),
            Name = row[1].ToString(),
            HourTitle = ShiftsTab.Rows.IndexOf(row) < 10 ? $"Ora0{ShiftsTab.Rows.IndexOf(row)}" : $"Ora{ShiftsTab.Rows.IndexOf(row)}",
            Ora00 = Convert.ToDouble(row[2].ToString()),
            Ora01 = Convert.ToDouble(row[3].ToString()),
            Ora02 = Convert.ToDouble(row[4].ToString()),
            Ora03 = Convert.ToDouble(row[5].ToString()),
            Ora04 = Convert.ToDouble(row[6].ToString()),
            Ora05 = Convert.ToDouble(row[7].ToString()),
            Ora06 = Convert.ToDouble(row[8].ToString()),
            Ora07 = Convert.ToDouble(row[9].ToString()),
            Ora08 = Convert.ToDouble(row[10].ToString()),
            Ora09 = Convert.ToDouble(row[11].ToString()),
            Ora10 = Convert.ToDouble(row[12].ToString()),
            Ora11 = Convert.ToDouble(row[13].ToString()),
            Ora12 = Convert.ToDouble(row[14].ToString()),
            Ora13 = Convert.ToDouble(row[15].ToString()),
            Ora14 = Convert.ToDouble(row[16].ToString()),
            Ora15 = Convert.ToDouble(row[17].ToString()),
            Ora16 = Convert.ToDouble(row[18].ToString()),
            Ora17 = Convert.ToDouble(row[19].ToString()),
            Ora18 = Convert.ToDouble(row[20].ToString()),
            Ora19 = Convert.ToDouble(row[21].ToString()),
            Ora20 = Convert.ToDouble(row[22].ToString()),
            Ora21 = Convert.ToDouble(row[23].ToString()),
            Ora22 = Convert.ToDouble(row[24].ToString()),
            Ora23 = Convert.ToDouble(row[25].ToString()),
        };

            Map.Add(mapCollection);

    }; 
    return Map;
}

Can anyone help me please, i just want to run this without freezing the ui

Rand Random
  • 7,300
  • 10
  • 40
  • 88
Erjon
  • 923
  • 2
  • 7
  • 32
  • What type stored inside `ShiftsTab.Rows`? Why are you calling `ToString()` then converting that string to `double`? – SᴇM Nov 28 '18 at 12:40
  • In your current code Map.Add() is executed synchronously. What was your problem, when you added Task.Run? – Christoph Lütjen Nov 28 '18 at 12:40
  • @SeM i'm calling some data from a database, i removed ToString() and is the same result. I did it like this cause im a newbie in c#. – Erjon Nov 28 '18 at 12:44
  • @ChristophLütjen the same result the UI freezes in the same point. – Erjon Nov 28 '18 at 12:44
  • 1
    Where are you calling this method from? I guess it must be from some event handler. If that's the case please be sure to mark that method as `async void` and await your long running method. – Karel Tamayo Nov 28 '18 at 12:45
  • @KarelTamayo yes of course i'm calling it with proper async await. i think everything has to do with parallel.foreach – Erjon Nov 28 '18 at 12:51
  • 1
    What do you mean by `Parallel.Foreach`? I cannot see that in the code you posted. – Haukinger Nov 28 '18 at 13:02
  • @Haukinger, i was thinking if i have to use Parallel.Foreach – Erjon Nov 28 '18 at 13:04

1 Answers1

1

You are saying that Task.Run didn't work for you. Maybe you forgot the await keyword?

Wrap your computationally expensive code into await Task.Run(() => {...}); like so:

private async Task<ObservableCollection<ShiftPageListItemViewModel>> GetMapAsync()
{
    mDbConnect = new DBConnect();

    var ShiftsTab = new DataTable();

    ShiftsTab = await mDbConnect.MapAsync(Date.ToString("yyyy-MM-dd"));

    var Map = new ObservableCollection<ShiftPageListItemViewModel>();

    await Task.Run(() =>
    {
        foreach (DataRow row in ShiftsTab.Rows)
        {
            var mapCollection = new ShiftPageListItemViewModel
            {
                BorderTag = row[0].ToString(),
                Name = row[1].ToString(),
                HourTitle = ShiftsTab.Rows.IndexOf(row) < 10 ? $"Ora0{ShiftsTab.Rows.IndexOf(row)}" : $"Ora{ShiftsTab.Rows.IndexOf(row)}",
                Ora00 = Convert.ToDouble(row[2].ToString()),
                Ora01 = Convert.ToDouble(row[3].ToString()),
                Ora02 = Convert.ToDouble(row[4].ToString()),
                Ora03 = Convert.ToDouble(row[5].ToString()),
                Ora04 = Convert.ToDouble(row[6].ToString()),
                Ora05 = Convert.ToDouble(row[7].ToString()),
                Ora06 = Convert.ToDouble(row[8].ToString()),
                Ora07 = Convert.ToDouble(row[9].ToString()),
                Ora08 = Convert.ToDouble(row[10].ToString()),
                Ora09 = Convert.ToDouble(row[11].ToString()),
                Ora10 = Convert.ToDouble(row[12].ToString()),
                Ora11 = Convert.ToDouble(row[13].ToString()),
                Ora12 = Convert.ToDouble(row[14].ToString()),
                Ora13 = Convert.ToDouble(row[15].ToString()),
                Ora14 = Convert.ToDouble(row[16].ToString()),
                Ora15 = Convert.ToDouble(row[17].ToString()),
                Ora16 = Convert.ToDouble(row[18].ToString()),
                Ora17 = Convert.ToDouble(row[19].ToString()),
                Ora18 = Convert.ToDouble(row[20].ToString()),
                Ora19 = Convert.ToDouble(row[21].ToString()),
                Ora20 = Convert.ToDouble(row[22].ToString()),
                Ora21 = Convert.ToDouble(row[23].ToString()),
                Ora22 = Convert.ToDouble(row[24].ToString()),
                Ora23 = Convert.ToDouble(row[25].ToString()),
            };

            Map.Add(mapCollection);
        };

    }); 
    return Map;
}
sebrockm
  • 5,733
  • 2
  • 16
  • 39
  • I've tried even like this but there is a delay on `Map.Add(mapCollection);` – Erjon Nov 28 '18 at 12:55
  • @Eriontp I don't know how big this delay is, but if `Map.Add(mapCollection)` is also inside of `Task.Run` then your UI stays responsive IF `GetMapAsync()` itself is also called with the `await` keyword. However, if this is not your issue, but you simply wish the results to show up earlier, then there is no other way than speed up your code. – sebrockm Nov 28 '18 at 12:58
  • The delay is for only half a second, the problem is that why should it be this delay when `Map.Add(mapCollection)` is inside `Task.Run`, and i has looking if i'm missing something out. anyway thank you – Erjon Nov 28 '18 at 13:02
  • @Eriontp just to make sure: when you're talking about "delay", do you simply mean that it takes some time until the result is visible, or do you mean that your UI is not responsive during that time, i.e. you cannot click it? – sebrockm Nov 28 '18 at 13:05
  • You are right, sorry. the UI freezes for half a second when calling this code. – Erjon Nov 28 '18 at 13:06
  • and im calling it like this `public async Task SyncMapNotificationsAsync() { MMapTable = await GetMapAsync(); }` where `MMapTable` is an observablecollection: `private ObservableCollection MMapTable { get; set; }` – Erjon Nov 28 '18 at 13:10
  • where exactly does it freeze? at `Map.Add` or at `MMapTable =`? – Haukinger Nov 28 '18 at 13:14
  • @Haukinger, it's so strange cause i changed the way i call this into `public void SyncMapNotificationsAsync() { Task.Run(async() => { MMapTable = await GetMapAsync(); }); } ` and the code is a little bit more light. thank you. – Erjon Nov 28 '18 at 13:23
  • @Eriontp If this is really better than before, that very likely means that there is some flaw somewhere in your async-await chain of methods. Because in your last comment `SyncMapNotificationsAsync` is doing nothing else but starting a task, which of cause is fast. If it wasn't fast before, that means it must have been called in a way that it not only started a task but also waited *synchronously* for it to finish. – sebrockm Nov 28 '18 at 14:34