-1

I have this code that deserialize JSON from url but the GUI still gets blocked and I don't know how to sort it out.

Button Code:

private void button1_Click(object sender, EventArgs e)
{
    var context = TaskScheduler.FromCurrentSynchronizationContext();
    string RealmName = listBox1.Items[listBox1.SelectedIndex].ToString();
    Task.Factory.StartNew(() => JsonManager.GetAuctionIndex().Fetch(RealmName)
    .ContinueWith(t =>
    {
        bool result = t.Result;
        if (result)
        {
            label1.Text = JsonManager.GetAuctionIndex().LastUpdate + " ago";
            foreach (string Owner in JsonManager.GetAuctionDump().Fetch(JsonManager.GetAuctionIndex().DumpURL))
            {
                listBox2.Items.Add(Owner);
            }
        }
    },context));
}

Fetch and deserialize function

public async Task<bool> Fetch(string RealmName)
{           
    using (WebClient client = new WebClient())
    {
        string json = "";
        try
        {
            json = client.DownloadString(new UriBuilder("my url" + RealmName).Uri);                 
        }
        catch (WebException)
        {
            MessageBox.Show("");
            return false;
        }
        catch
        {
            MessageBox.Show("An error occurred");
            Application.Exit();
        }
        var results = await JsonConvert.DeserializeObjectAsync<RootObject>(json);

        TimeSpan duration = DateTime.Now - Utilities.UnixTimeStampToDateTime(results.files[0].lastModified);
        LastUpdate = (int)Math.Round(duration.TotalMinutes, 0);
        DumpURL = results.files[0].url;
        return true;
    }
}
Cœur
  • 37,241
  • 25
  • 195
  • 267
lorigio
  • 89
  • 1
  • 3
  • 9
  • You should use [`Task.Run` not `Task.Factory.StartNew`](https://stackoverflow.com/a/38423507/542251) unless you specifically want to override the default options of your `Task` – Liam Nov 14 '18 at 15:06

1 Answers1

0

Inside your Fetch method you should also use await for downloading your string data from the WebClient by changing it to:

json = await client.DownloadStringAsync(new UriBuilder("my url" + RealmName).Uri);                 

And instead of using a Task with a continuation you should use await also in your button eventhandler:

private async Task button1_Click(object sender, EventArgs e)
{
    string RealmName = listBox1.Items[listBox1.SelectedIndex].ToString();

    bool result = await JsonManager.GetAuctionIndex().Fetch(RealmName);
    if (result)
    {
        label1.Text = JsonManager.GetAuctionIndex().LastUpdate + " ago";
        foreach (string Owner in await JsonManager.GetAuctionDump().Fetch(JsonManager.GetAuctionIndex().DumpURL))
        {
            listBox2.Items.Add(Owner);
        }
    }
}

The continuation is now setup by the C# compiler. By default, it will continue on the UI thread so you don't have to manually capture the current synchronization context. By awaiting your Fetch method, you automatically unwrap the Task to a bool and then you can continue executing code on the UI thread.

Wouter de Kort
  • 39,090
  • 12
  • 84
  • 103
  • Thank you it works now with some adjustment. I used DownloadStringTaskAsync instead of DownloadStringAsync – lorigio Apr 06 '13 at 17:15