Winforms 最佳实践:在等待异步方法时阻止执行
我正在尝试调整一个现有的程序(内部编写的),以使用与最初不同的库。我已经抽象了大多数特定于库的代码(似乎是最简单的部分) 问题是,旧库将使用阻塞方法执行调用,我们的内部程序希望调用阻塞方法,但新库使用异步方法 我想知道等待异步操作完成的最佳实践是什么。我的第一个想法是使用一个名为completed的布尔标志,并在while循环中旋转,直到completed==trueWinforms 最佳实践:在等待异步方法时阻止执行,winforms,c#-3.0,asynchronous,multithreading,blocking,Winforms,C# 3.0,Asynchronous,Multithreading,Blocking,我正在尝试调整一个现有的程序(内部编写的),以使用与最初不同的库。我已经抽象了大多数特定于库的代码(似乎是最简单的部分) 问题是,旧库将使用阻塞方法执行调用,我们的内部程序希望调用阻塞方法,但新库使用异步方法 我想知道等待异步操作完成的最佳实践是什么。我的第一个想法是使用一个名为completed的布尔标志,并在while循环中旋转,直到completed==true 我应该注意到,这是为了快速证明我试图为我的利益相关者制定的概念,如果利益相关者在项目上签字,我将重写我们计划中有问题的部分。但目
我应该注意到,这是为了快速证明我试图为我的利益相关者制定的概念,如果利益相关者在项目上签字,我将重写我们计划中有问题的部分。但目前,我只需要等待调用异步方法的函数阻塞,直到异步调用完成将倒计时锁存器传递给异步方法,然后等待锁存器。当异步方法完成时,它将在倒计时锁存器上通知您,并且可以继续执行。原则上也可以使用监视器,但如果异步方法在调用wait之前完成,并且因此错过了notify,那么这种情况是不安全的
哦,在.NET世界中,倒计时闩锁被称为倒计时事件:我想你应该使用类似于国旗的东西,而不是国旗 为了做到这一点,该库需要有一个事件在异步调用完成后通知您。它看起来是这样的:
private static Semaphore mySemaphore = new Semaphore(0, 1);
static void Main(string[] args)
{
Console.WriteLine("Waiting on async call");
(new Thread(ASyncCallCompleted)).Start();
mySemaphore.WaitOne();
Console.WriteLine("Waiting Completed");
}
private static void ASyncCallCompleted()
{
Thread.Sleep(5000);
mySemaphore.Release();
}
编辑#2:根据Thorarin的建议;听起来这个类是为处理.Net中的类似情况而设计的:
private static AutoResetEvent mySync = new AutoResetEvent(false);
static void Main(string[] args)
{
Console.WriteLine("Waiting on async call");
(new Thread(ASyncCallCompleted)).Start();
mySync.WaitOne();
Console.WriteLine("Waiting Completed");
Console.Read();
}
private static void ASyncCallCompleted()
{
Thread.Sleep(5000);
mySync.Set();
}
这最多只能同时调用一次
BlockingCall
。否则,您将需要单独的AutoResetEvent
实例来确定哪个调用已完成。无论如何:
delegate void Callback();
class BlockAsync
{
AutoResetEvent _waitHandle = new AutoResetEvent(false);
public void BlockingCall()
{
AsyncCall(AsyncCallCompleted);
_waitHandle.WaitOne();
}
void AsyncCall(Callback callback)
{
// Example is not actually asynchronous, to demonstrate the solution
// is free of race conditions.
callback();
}
void AsyncCallCompleted()
{
_waitHandle.Set();
}
}
除非异步方法很快,并且在waitone之前调用release,否则这将起作用……我稍微更改了答案;我认为如果信号量在waitone之前被释放方法被调用时,它不会阻止
AutoResetEvent
比信号量
更有意义。此外,如果您想考虑多线程环境中的多个同时调用,则需要修改此示例。倒计时锁存器和信号量非常相似,但通常用于不同的目的。参见@disown:John提到的种族条件。如果异步调用完成得太快,可能会导致信号量异常
AutoResetEvent
也可以,因为实际上不需要计算任何值。而且由于CountdownEvent
也仅为.NET4.0版本。。。我很高兴他们加了这个。