如何在事件被触发后才返回C#方法?

时间:2014-01-14 20:31:20

标签: c# .net events event-handling synchronization

我有一个DLL SomeLib.dll,其中包含DeleteHandler个对象:

public class DeleteHandler
{
    private _handlerToServerObj;

    public DeleteHandler()
    {
        _handlerToServerObj = new HandlerToServerObj(/* ... */);
        _handlerToServerObj.OnDelete += new OnDeleteEventHandler(OnDeleteEH);
    }

    public void Delete(string id)
    {
        _handlerToServerObj.Delete(id);
    }

    private void OnDeleteEH(string id)
    {
        //
    }
}

工作原理:

  • _handlerToServerObj.Delete(id)正在向服务器发送消息,并且该呼叫立即返回;
  • 当服务器成功删除该项目时,它将触发OnDelete事件。

此库通常由WinForms应用程序使用。

通常情况下,我希望Delete()方法在服务器确实删除项目后返回 (即OnDelete事件被触发,因此,执行OnDeleteEH

我尝试使用ManualResetEvent,但没有成功(即永远不会调用OnDeleteEH):

private ManualResetEvent _waitHandle = new ManualResetEvent(false);

public void Delete(string id)
{
    _waitHandler.Reset();
    _handlerToServerObj.Delete(id);
    _waitHandle.WaitOne();
}

private void OnDeleteEH(string id)
{
    //
    _waitHandle.Set();
}

或者:

private ManualResetEvent _waitHandle = new ManualResetEvent(false);

public void Delete(string id)
{
    _waitHandler.Reset();
    Thread thread = new Thread(PrivateDelete);
    thread.Start(id);
    _waitHandle.WaitOne();
}

private void PrivateDelete(string id)
{
    _handlerToServerObj.Delete(id);
}

private void OnDeleteEH(string id)
{
    //
    _waitHandle.Set();
}

这个设计有效吗?如果是的话,我在实施过程中犯的错误是什么?如果不是,请你建议更正?

[编辑1]

纠正了与代码相关的一些错误。

1 个答案:

答案 0 :(得分:4)

你在方法中隐藏等待句柄,这导致你等待一个永远不会被设置的句柄。

您需要使用实例字段,而不是在_waitHandle中声明名为Delete的新变量。

当然,如果使用匿名事件处理程序而不是其他方法,则可以简化代码:

public void Delete(string id)
{
    ManualResetEvent waitHandle = new ManualResetEvent(false);
    _handlerToServerObj.OnDelete += () => waitHandle.Set();
    _handlerToServerObj.Delete(id);
    waitHandle.WaitOne();
}

如果你像这样使用一个闭包,那么你根本不需要把柄作为一个实例字段。


说完所有这些后,如果你在桌面UI应用程序的上下文中使用它,你可能不会想要有一个阻塞方法;你可能想要异步地做这样的工作,而不是同步。如果在UI线程中调用,您将阻止UI线程,并创建一个新的工作线程,以便它可以在一些异步IO操作上花费所有时间阻塞,这简直是浪费。虽然可能存在一些您真正想要等待此事件的情况,但请花点时间确保它适合您的具体情况。