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

C#方法如何仅在触发事件后返回?,c#,.net,events,event-handling,synchronization,C#,.net,Events,Event Handling,Synchronization,我有一个DLLSomeLib.DLL,其中包含一个DeleteHandler对象: public class DeleteHandler { private _handlerToServerObj; public DeleteHandler() { _handlerToServerObj = new HandlerToServerObj(/* ... */); _handlerToServerObj.OnDelete += new OnD

我有一个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)
    {
        //
    }
}
工作原理:

  • \u handlerToServerObj.Delete(id)
    正在向服务器发送消息,呼叫立即返回
  • 当服务器成功删除该项目时,它将触发
    OnDelete
    事件
此库通常由
WinForms
应用程序使用

通常,我希望
Delete()
方法仅在服务器确实删除了该项后返回(即,触发
OnDelete
事件,因此执行
ondeleteh

我尝试过使用
ManualResetEvent
,但没有成功(即从未调用
ondeleteh
):

或:

这个设计有效吗?如果是,我在实施过程中犯了哪些错误?如果没有,你能建议改正吗

[编辑1]


更正了与代码有关的一些错误。

您正在方法中隐藏等待句柄,这会导致您等待从未设置的句柄

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

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

public void Delete(string id)
{
    ManualResetEvent waitHandle = new ManualResetEvent(false);
    _handlerToServerObj.OnDelete += () => waitHandle.Set();
    _handlerToServerObj.Delete(id);
    waitHandle.WaitOne();
}
如果在这里使用这样的闭包,那么根本不需要将句柄作为实例字段



话虽如此,如果您在桌面UI应用程序的上下文中使用它,您可能不希望使用阻塞方法;您可能希望以异步方式而不是同步方式完成这样的工作。如果在UI线程中调用,您将阻塞UI线程,而创建一个新的工作线程只是为了让它能够将所有时间都花在某些异步IO操作上,这是浪费。虽然在某些情况下您确实希望等待此事件,但请花点时间确保它适合您的具体情况。

您在方法中隐藏了等待句柄,这会导致您等待从未设置的句柄

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

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

public void Delete(string id)
{
    ManualResetEvent waitHandle = new ManualResetEvent(false);
    _handlerToServerObj.OnDelete += () => waitHandle.Set();
    _handlerToServerObj.Delete(id);
    waitHandle.WaitOne();
}
如果在这里使用这样的闭包,那么根本不需要将句柄作为实例字段



话虽如此,如果您在桌面UI应用程序的上下文中使用它,您可能不希望使用阻塞方法;您可能希望以异步方式而不是同步方式完成这样的工作。如果在UI线程中调用,您将阻塞UI线程,而创建一个新的工作线程只是为了让它能够将所有时间都花在某些异步IO操作上,这是浪费。虽然在某些情况下您确实希望等待此事件,但请花点时间确保它适合您的具体情况。

+1请注意,这解决了问题所涉及的直接问题。在UI线程上使用同步等待(
Sleep
WaitOne
…)至少会冻结UI,或者在其他线程需要将结果发布到UI线程时会导致死锁。考虑使用新的<代码> Aycy /<代码>如果可能的话,请等待< /代码>。@ AlexeiLevenkov Yeah,正在把一个注释放在一个编辑中。谢谢你的回复。代码>\u handlerToServerObj.OnDelete+=waitHandle.Set()无法工作,因为编译器抱怨它无法隐式地将类型“bool”转换为“OnDelete”。此外,我需要
ondeleteh
事件处理程序来进行一些验证。我在写问题时犯了一个错误(即,将
\u waitHandle
声明在错误的位置)。因此,我编辑了这个问题,现在事情似乎已经准备就绪。当然,问题仍然存在。建议?@Yeseanul事件处理程序没有编译是因为我忘记添加lambda部分;这是编辑的。如果处理者还需要做其他事情,就让它做其他事情;没关系。@Yeseanul鉴于这种情况,我们可以100%确信这不应该同步进行。这将阻塞UI线程,直到该操作完成;即使你能做到,你也不会想的。您应该异步编程,这意味着您的方法应该接受回调,并且调用方应该提供在删除发生后运行的回调方法。+1注意,这解决了问题所涉及的直接问题。在UI线程上使用同步等待(
Sleep
WaitOne
…)至少会冻结UI,或者在其他线程需要将结果发布到UI线程时会导致死锁。考虑使用新的<代码> Aycy /<代码>如果可能的话,请等待< /代码>。@ AlexeiLevenkov Yeah,正在把一个注释放在一个编辑中。谢谢你的回复。代码>\u handlerToServerObj.OnDelete+=waitHandle.Set()无法工作,因为编译器抱怨它无法隐式地将类型“bool”转换为“OnDelete”。此外,我需要
ondeleteh
事件处理程序来进行一些验证。我在写问题时犯了一个错误(即,将
\u waitHandle
声明在错误的位置)。因此,我编辑了这个问题,现在事情似乎已经准备就绪。当然,问题仍然存在。建议?@Yeseanul事件处理程序没有编译是因为我忘记添加lambda部分;这是编辑的。如果处理者还需要做其他事情,就让它做其他事情;没关系。@Yeseanul鉴于这种情况,我们可以100%确信这不应该同步进行。这将阻塞UI线程,直到该操作完成;即使你能做到,
public void Delete(string id)
{
    ManualResetEvent waitHandle = new ManualResetEvent(false);
    _handlerToServerObj.OnDelete += () => waitHandle.Set();
    _handlerToServerObj.Delete(id);
    waitHandle.WaitOne();
}