Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C#windows服务中使用异步事件处理程序_C#_Asynchronous_Async Await_Windows Services - Fatal编程技术网

在C#windows服务中使用异步事件处理程序

在C#windows服务中使用异步事件处理程序,c#,asynchronous,async-await,windows-services,C#,Asynchronous,Async Await,Windows Services,我有一个C#(4.8)windows服务。它所做的只是在启动时注册一些事件处理程序,当消息到达时,messagequeue会调用这些事件处理程序,事件处理程序会对其进行处理。事件处理程序调用库方法来处理它。这都是同步的。现在,作为使所有内容都成为异步等待模式的一部分,库中的所有处理逻辑现在都重写为异步等待。现在的问题是windows服务中的事件处理程序。当我让他们异步无效时,我得到一个错误,说这需要一个任务。我知道在UI应用程序中,我们可以使异步无效。在windows服务中不允许使用它吗?也就是

我有一个C#(4.8)windows服务。它所做的只是在启动时注册一些事件处理程序,当消息到达时,messagequeue会调用这些事件处理程序,事件处理程序会对其进行处理。事件处理程序调用库方法来处理它。这都是同步的。现在,作为使所有内容都成为异步等待模式的一部分,库中的所有处理逻辑现在都重写为异步等待。现在的问题是windows服务中的事件处理程序。当我让他们异步无效时,我得到一个错误,说这需要一个任务。我知道在UI应用程序中,我们可以使异步无效。在windows服务中不允许使用它吗?也就是说,我将它设为async void,那么我就有处理异常的问题,因为它们不会在那里被捕获,因为没有任务。我还需要考虑W.R.T的同步化上下文是否为Win服务,毕竟Win Services有默认的上下文,事件处理程序在Acyc.

< P>中可以捕获上下文。因此,它无法知道您何时完成事件处理。如果您对用例中的这种行为没有意见,只需在处理程序中添加try-catch(如您所说,无法处理
async void
方法引发的错误。如果必须在将控件返回给发送方之前完成处理,请使用
Wait()
在您的异步处理程序上。据我所知,Windows服务没有同步上下文,您不会在这里出现死锁。

如果您想使用,那么您将被困在
void
中。这是无法避免的。如果您想在事件处理程序中使用
异步
代码,那么您将被困在
异步void

这并不一定不好。事件实际上只是一个“hey this Incided”的通知,然后继续进行。引发事件的代码的任务不是关心事件处理程序做了什么,或者何时或是否成功完成。它的任务是说“hey this Incided”

大多数情况下,关注点的分离有时会变得模糊。例如,以WebForms中的事件为例。这是一个窗口即将关闭的通知。在事件处理程序返回后,窗口将关闭。但是
wait
通过稍后返回并完成其余工作来工作。这意味着asynchronous
Closing
事件处理程序不会在窗口关闭之前完全完成,这当然是正确的

因此,如果:

  • 您的代码不依赖于事件处理程序在执行其他工作之前成功完成
  • 您的代码不会处理或关心事件处理程序代码中的异常,或者
  • 您希望允许多个事件处理程序订阅
然后只使用普通的事件处理程序

另一种方法是将异步委托作为参数初始化到一个初始化方法(或者如果需要的话,甚至是一个属性)。例如,考虑此类:

public class Test {
    private readonly Func<Task> _somethingHappenedHandler;
    
    public Test(Func<Task> somethingHappenedHandler) {
        _somethingHappenedHandler = somethingHappenedHandler;
    }
    
    public async Task DoSomething() {
        //do something
        await _somethingHappenedHandler();
    }
}
如果您需要知道事件处理程序在继续之前已成功完成,则可以使用此方法。但您将失去订阅多个事件处理程序的能力,但这可能不是您关心的问题


您还应该考虑如何处理处理处理程序中发生的异常。您是否会忽略这些异常并将此负担放在事件处理程序代码上?还是以某种方式处理它们?

“当我将它们设置为异步无效时,我会出错,说它需要成为一项任务。”-编译器不会给你任何这样的错误。你能显示你的代码吗?整个原因
async void
甚至被允许用于事件处理程序。这是一个警告而不是错误。对此很抱歉。重点是我不想使用async void,因为它不是一个与UI相关的事件处理程序,而是一个基于库的事件处理程序。不确定这是否会造成不同虽然问题是我不想使用Wait/Result,也可能我正在寻找一个返回任务的自定义事件,以便我可以在事件处理程序中正确使用Wait。只需要了解事件触发将如何发生,特别是由第三方库公开的事件。我想也许我可以捕获由MSMQ,然后从处理程序中触发“我的自定义事件”,但此时它再次成为“同步到异步调用”。@Krishnan您必须决定是否可以以“触发并忘记”的方式处理该事件。如果不能,则除了
等待
”异步处理程序之外,您没有其他选择。
public async Task SomethingHappened() {
    await Task.Delay(1000);
    Console.WriteLine("Something happened");
}

var test = new Test(SomethingHappened);
await test.DoSomething();