简体   繁体   English

如何等待C#中的方法完成?

[英]How to wait until method complete in C#?

I have this C# code, it works but it won't wait until the method completed 我有这个C#代码,它可以工作,但是不会等到方法完成

foreach (var listBoxItem in visualListBox1.Items)
{
    lblCursor.Text = "Processing.. " + listBoxItem;
    Thread t = new Thread(() => extract_group(listBoxItem.ToString()));
    t.IsBackground = false; 
    t.Name = "Group Scrapper";
    t.Start();
}

How to wait until extract_group method is done before moving to the next listBoxItem ? 在移动到下一个listBoxItem之前如何等待extract_group方法完成?

I used t.join() but it made the UI unresponsive. 我使用了t.join()但它使UI无响应。

Using async/await helps you to not block main thread. 使用异步/等待可以帮助您不阻塞主线程。

public async Task ExtractGroupAsync()
{
   ... (logic of the method)
   ... (you should use async methods here as well with await before executing those methods)
}

You execute this "ExtractGroup" task like: 您可以执行以下“ ExtractGroup”任务:

var example = await ExtractGroupAsync();

It makes GUI unresponsive, because you are on GUI thread. 由于您在GUI线程上,因此它使GUI无法响应。 Run whole code, in separate thread. 在单独的线程中运行整个代码。 Note: when you want to access GUI elements from another thread, you should use invoke, for example: 注意:当您要从另一个线程访问GUI元素时,应使用invoke,例如:

t.Invoke(() => t.Name = "Group Scrapper");

If you want to stick with Thread I recommend using a WaitHandle eg AsyncManualResetEvent Class . 如果您想坚持使用线程,我建议使用WaitHandle,例如AsyncManualResetEvent Class This approach allows to make a thread wait without blocking CPU (eg spinlock). 这种方法可以使线程等待,而不会阻塞CPU(例如,自旋锁)。 Your provided example would become: 您提供的示例将变为:

private static AsyncManualResetEvent mre = new AsyncManualResetEvent(false, true);
public async Task DoSomethingAsync(...)
{
  foreach (var listBoxItem in visualListBox1.Items)
  {
    lblCursor.Text = "Processing.. " + listBoxItem;
    Thread t = new Thread(() => ExtractGroup(listBoxItem.ToString()));
    t.IsBackground = false; 
    t.Name = "Group Scrapper";
    t.Start();

    // Wait for signal to proceed without blocking resources
    await mre.WaitAsync();
  }
}

private void ExtractGroup(string groupName)
{
  // Do something ...

  // Signal handle to release all waiting threads (makes them continue).
  // Subsequent calls to Set() or WaitOne() won't show effects until Rest() was called
  mre.Set();

  // Reset handle to make future call of WaitOne() wait again.
  mre.Reset();
}

Another solution would be to go with the TPL and use Task instead of Thread : 另一个解决方案是使用TPL并使用Task而不是Thread

public async Task DoWorkAsync()
{
  foreach (var listBoxItem in visualListBox1.Items)
  {
    lblCursor.Text = "Processing.. " + listBoxItem;

    // Wait for signal to proceed without blocking resources
    await Task.Run(() => ExtractGroup(listBoxItem.ToString()));
  }
}  

The issue with your code sample is, that you are currently on the main thread, the UI thread. 代码示例的问题是,您当前位于主线程UI线程上。 Calling Thread.Join() does what you think it does: it blocks the waiting thread until the running thread completes. 调用Thread.Join()会执行您认为的工作:阻塞正在等待的线程,直到运行线程完成。 But as mentioned, the waiting thread is the UI thread, so the UI becomes unresponsive and can even deadlock in some scenario. 但是如前所述,等待线程是UI线程,因此UI在某些情况下会变得无响应甚至死锁。 When you use async/await your invocations become asynchronous and hence awaitable without blocking the UI thread. 当您使用async / await时,您的调用将变为异步,因此可以等待,而不会阻塞UI线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM