如何阻止异步调用完成?

时间:2009-12-21 21:15:31

标签: c# .net asynchronous

我有一个调用异步方法的方法,以及异步方法完成时触发的回调。

我希望我的方法看起来是同步的,所以我创建了一个AutoResetEvent,称为asyncrhonous方法,在AutoResetEvent实例上调用WaitOne(),我在回调方法中调用Set()。像这样的东西(本例简化):

private System.Threading.AutoResetEvent waitRun_m;
public void RunSynchronous()
{
    waitRun_m = new System.Threading.AutoResetEvent(false);
    CallAsynchronousMethod();

    waitRun_m.WaitOne();
}

private void Callback()
{
    waitRun_m.Set();
}

现在,可以在调用WaitOne()之前完成对CallAsynchronousMethod的调用 - 导致在WaitOne()之前调用Set()。有没有更好的方法来避免这个潜在的问题?

3 个答案:

答案 0 :(得分:7)

我相信这会回答你的问题:

  

调用Set信号AutoResetEvent释放等待线程。 AutoResetEvent保持信号状态,直到释放单个等待线程,然后自动返回到非信号状态。 如果没有线程在等待,状态将无限期地发出信号。

但是,您必须小心,因为现在RunSynchronous看起来不是线程安全的。如果两个不同的线程以重叠的方式调用它,那么一切都会破裂。

答案 1 :(得分:3)

这不是问题,在您完全支持WaitOne之前获取Set的事件。如果不是这种情况,AutoResetEvent将无法使用。

答案 2 :(得分:1)

Daniel和nobugz说使用AutoResetEvent可能很危险。你可能会打电话 当异步操作非常短时,在调用waitRun_m.Set();之前waitRun_m.WaitOne();。我更喜欢这样的东西。这样您就可以确定首先进入等待状态,然后调用Pulse方法。另外,您不必Close经常被遗忘的AutoResetEvent

private readonly object m_lock = new object();
public void RunSynchronous()
{
    lock(m_lock) {
        CallAsynchronousMethod();
        Monitor.Wait(m_lock);
    }
}

private void Callback()
{
    lock(m_lock)
        Monitor.Pulse(m_lock);
}