C#:阻止函数调用直到满足条件

我正在开发一个C#Winforms应用程序,部分应用程序将使用AsyncUpload将文件上传到Web服务器(使用它,因为需要使用porgress回调),在C#程序中

我有一个简单的for循环调用上传function

for(int i=0;i < 10 ; i++) { Uploadfun(); } 

这种乐趣有些神奇:

 Uploadfun() { // Logic comes here // webClient.UploadFileAsync runs a 2nd thread to perform upload .. webClient.UploadFileAsync(uri, "PUT", fileNameOnHD); } 

并且在完成异步上载时调用的回调

 Upload_Completed_callback() { //Callback event } 

编辑

逻辑顺序:

  1. 乐趣被召唤(来自循环)
  2. 有趣的逻辑被执行和完成..
  3. 回到for循环
  4. 当UploadFileAsync(在另一个线程中运行某些逻辑)结束时,最终将调用回调

问题是在第3点,当执行回到for循环时,我需要阻止循环继续,直到调用回调。

因此,如果我理解正确,您需要调用UploadFileAsync然后阻止,直到异步调用达到您的回调为止。 如果是这样,我会使用AutoResetEvent ie

 private readonly AutoResetEvent _signal = new AutoResetEvent(false); fun() { // Logic comes here // runs a 2nd thread to perform upload .. calling "callback()" when done webClient.UploadFileAsync(uri, "PUT", fileNameOnHD); _signal.WaitOne(); // wait for the async call to complete and hit the callback } callback() { //Callback event _signal.Set(); // signal that the async upload completed } 

使用AutoResetEvent意味着在调用Set并且等待线程通过WaitOne接收信号后,状态会自动重置

在C#方法中默认阻止,所以你不需要做任何事情。 我假设你出于某种原因调用了一个非阻塞方法来启动一个后台任务/线程/什么,并在完成后给你一个回调。 您想以同步方式调用此异步方法。

你可以从回调中调用fun 。 沿着这些方向的东西(伪代码):

 int n; callFunTenTimes() { n = 0; fun(n); } callback() { ++n; if (n < 10) fun(n); else print("done"); } 

这类似于延续传递风格 。

此方法的一个优点是,您还可以使方法异步,而无需添加任何额外的线程,锁或额外的逻辑 - 您只需提供客户端可以订阅的回调函数。 它在事件驱动的环境中运行良好。

Zebrabox确实使用WaitHandle。 虽然Juliet的解决方案确实有效,但执行自旋等待的线程将占用与WaitHandle成比例的大量处理器,而WaitHandle实际上将处于空闲状态。

问题出在这里:

 for(int i=0;i < 10 ; i++) { fun(); <-- if we block until this function finishes here, we stop the UI thread } 

你正在做的是顺序。 如果您无法阻止UI线程,请将循环移出UI线程:

 volatile downloadComplete; void DownloadUpdates() { ThreadPool.QueueUserWorkItem(state => for(int i = 0; i < 10; i++) { downloadComplete = false; webClient.UploadFileAsync(uri, "PUT", fileNameOnHD); while(!downloadComplete) { Thread.Sleep(1); } }); } Upload_Completed_callback() { downloadComplete = true; } 

现在,您可以在不停止UI线程的情况下阻止循环的执行,并且您还可以从webclient类中获得进度指示器的好处。