1

I used following code to execute the SourceCreator method without blocking UI.

string a =null; 
private string SourceCreator()
{
    string sum = textBox7.Text;
    sum = sum.Replace(" ", "+");

    string url = string.Format("https://www.aliexpress.com/wholesale?catId=0&initiative_id=SB_20220824221043&SearchText={0}&spm=a2g0o.productlist.1000002.0", sum);
    HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
    HttpWebResponse response = (HttpWebResponse)request.GetResponse();
    StreamReader sr = new StreamReader(response.GetResponseStream());
    // richTextBox2.Text += sr.ReadToEnd();
    a = sr.ReadToEnd();
    sr.Close();

    return a;
}

Here is button click event

private async void Timer4_Tick(object sender, EventArgs e)
{
    Task<string> task1 = new Task<string>(SourceCreator);
    task1.Start();
    string p = await task1;
    textBox10.Text = p;
}

I run this code, but this still blocking my UI of Windows form app. Could somebody tell me why?

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
herry jack
  • 11
  • 2
  • 3
    I think you may be missing where the UI is getting blocked? The HttpWebRequest is not async. This may be what you are looking for: https://stackoverflow.com/questions/202481/how-to-use-httpwebrequest-net-asynchronously – Zonus Aug 25 '22 at 18:57
  • 2
    Alternatively, you might get away with Task.Run( () => SourceCreator() ); But, I would work off the code on the link above. – Zonus Aug 25 '22 at 19:00
  • You might also want to look at using a newer API for Web requests, such as HttpClient, which is async by default. – gunr2171 Aug 25 '22 at 19:02
  • i am trying to understand that explanation on that link you provided.. – herry jack Aug 25 '22 at 19:03
  • I think in the answer they are saying you need to use the Async methods. They are different then the regular ones. At least if you are going to use Tasks and have stuff wait on them. HttpWebRequest.BeginGetResponse() But, also Zonus is right not sure where it's getting blocked exactly. – Byrd Aug 25 '22 at 19:21
  • try below solution https://stackoverflow.com/questions/46942934/issues-with-async-blocking-gui-thread-winforms – Ashish.Wadekar Aug 25 '22 at 19:32
  • 2
    You almost never should use `Task` constructors. – Guru Stron Aug 25 '22 at 20:32
  • 1
    You are reading a UI object from a background thread, that is not allowed, and may block or crash. *Only access ui objects from the UI thread*. Also, the easiest way to find why the UI thread is blocked is to just use "break all" in the debugger and check what the Ui thread is doing. – JonasH Aug 25 '22 at 20:55
  • @JonasH I wonder if task constructor actually captures current scheduler/synchronization context so the code just works but blocks the UI thread. – Guru Stron Aug 25 '22 at 21:06
  • 1
    You should never, *ever* use `Task` constructors. ;) – Stephen Cleary Aug 25 '22 at 22:07
  • 1
    I think it's because you are waiting task1 to act upon the UI element textBox10. When you read this UI element from the background thread used in the async method it might be preventing the UI thread from reading/writing the same memory from the stack. I agree with Stephen Cleary and Guru Stron as well that it is very discouraged to use task constructors. [See this post for more info on constructors vs run](https://stackoverflow.com/questions/28057654/task-constructor-vs-task-run-with-async-action-different-behavior) – ExplodatedFaces Aug 25 '22 at 23:48

1 Answers1

2

You are not actually using any async methods here. You are just passing it to a Task constructor, which is not how you are supposed to do it, and may not work with the WinForms' SynchronizationContext.

HttpWebRequest is effectively deprecated, you should switch to HttpClient instead. And that has a full complement of async methods.

static HttpClient _client = new HttpClient();

private async Task<string> SourceCreator(string sum)
{
    sum = sum.Replace(" ", "+");
    string url = $"https://www.aliexpress.com/wholesale?catId=0&initiative_id=SB_20220824221043&SearchText={sum}&spm=a2g0o.productlist.1000002.0";

    using (var response = await _client.GetAsync(url))
    {
        var a = await response.Content.ReadAsStringAsync();
        return a;
    }
}

private async void Timer4_Tick(object sender, EventArgs e)
{
    string p = await SourceCreator(textBox7.Text);
    textBox10.Text = p;
}

If you want to use a StreamReader you can do it like this

private async Task<string> SourceCreator(string sum)
{
    sum = sum.Replace(" ", "+");
    string url = $"https://www.aliexpress.com/wholesale?catId=0&initiative_id=SB_20220824221043&SearchText={sum}&spm=a2g0o.productlist.1000002.0";

    using (var response = await _client.GetAsync(url))
    using (var stream = response.Content.ReadAsStreamAsync())
    using (var reader = new StreamReader(stream))
    {
        var a = // do stuff with reader here
        return a;
    }
}
Charlieface
  • 52,284
  • 6
  • 19
  • 43