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

发布于 2024-08-20 07:30:11 字数 746 浏览 4 评论 0原文

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

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

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

并且 fun 做了一些魔力:

Uploadfun()
  { 
  // Logic comes here

   // webClient.UploadFileAsync runs a 2nd thread to perform upload .. 
   webClient.UploadFileAsync(uri, "PUT", fileNameOnHD);  

 }

异步上传完成时调用的回调

Upload_Completed_callback()
{
  //Callback event
}

编辑

逻辑顺序:

  1. Fun 被调用(从循环)
  2. Fun 逻辑被执行并完成..
  3. 返回for循环
  4. 回调最终将被调用,当UploadFileAsync(正在另一个线程中运行一些逻辑)结束时

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

I am developing a C# Winforms application, part of the application will be uploading files to a webserver using AsyncUpload (using it,due to the need to use a porgress callback) , In the C# program

i got a simple for loop that calls The Uploading function

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

And the fun does some magic:

Uploadfun()
  { 
  // Logic comes here

   // webClient.UploadFileAsync runs a 2nd thread to perform upload .. 
   webClient.UploadFileAsync(uri, "PUT", fileNameOnHD);  

 }

And a callback that gets called when the Async upload is done

Upload_Completed_callback()
{
  //Callback event
}

Edit

The logic sequence:

  1. Fun gets called (from loop)
  2. Fun logic is executed and done..
  3. Goes back to for loop
  4. Callback will be called eventually, when UploadFileAsync (which is running some logic in another thread) will end

The problem is on the 3rd point, when the execution moves back to the for loop, i need to block the loop from continuing until the callback get called.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

眸中客 2024-08-27 07:30:11

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

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 发出信号

So if I understand correctly, you want to call UploadFileAsync then block until the async call has hit your callback. If so, I'd use AutoResetEvent i.e

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
 }

Using AutoResetEvent means that the state gets automatically reset after Set has been called and a waiting thread receives the signal via WaitOne

桜花祭 2024-08-27 07:30:11

在 C# 方法中,默认情况下会阻塞,因此您不需要执行任何操作。我假设由于某种原因您正在调用一个非阻塞方法来启动后台任务/线程/无论什么,并在完成时给您一个回调。您希望以同步方式调用此异步方法。

您可以从回调内部调用 fun。类似的东西(伪代码):

int n;

callFunTenTimes()
{
    n = 0;
    fun(n);
}

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

这类似于连续传递样式

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

In C# methods block by default, so you shouldn't need to do anything. I'm assuming that for some reason you are calling a non-blocking method that starts a background task / thread / whatever and gives you a callback when it's done. You want to call this asynchonous method in a synchronous manner.

You can call fun from inside the callback. Something along these lines (pseudo-code):

int n;

callFunTenTimes()
{
    n = 0;
    fun(n);
}

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

This is similar to continuation passing style.

An advantage to this method is that you can also make your method asynchronous without adding any extra threads, locks, or extra logic - you just supply a callback function which your client can subscribe to. It works well in an event-driven environment.

我最亲爱的 2024-08-27 07:30:11

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

Zebrabox does have it right using a WaitHandle.
While Juliet's solution does work, the thread performing the spin-wait will consume a significant amount of processor in proportion to the WaitHandle, which would essentially be sitting idle.

给不了的爱 2024-08-27 07:30:11

问题就在这里:

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 类中获得进度指示器的好处。

The problem is here:

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

What you're doing is sequential. And if you can't afford to block the UI thread, move the loop off the UI thread:

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;
}

Now you can block the execution of the loop without halting your UI thread, and you also get the benefit of progress indicators from the webclient class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文