【问题标题】:Exceptions are not received in caller when using ASYNC使用 ASYNC 时调用方未收到异常
【发布时间】:2018-05-31 05:29:11
【问题描述】:

我正在使用DispatcherTimer在指定的时间间隔处理一个方法

dispatcherTimer = new DispatcherTimer()
{
   Interval = new TimeSpan(0, 0, 0, 1, 0)
};
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);

这里是dispatcherTimer_Tick 方法

private void dispatcherTimer_Tick(object sender, EventArgs e)
{
    try
    {
        Task.Run(() => MethodWithParameter(message));
    }
    catch (Exception ex)
    {        
    }
}

我在这里调用 MQTTPublisher,这是一个 DLL 引用。

private async static void MethodWithParameter(string message)
{
    try
    {
        await MQTTPublisher.RunAsync(message);    
    }
    catch (Exception Ex)    
    {       
    }            
}

我无法捕获该 DLL 中引发的异常。如何让调用者获得异常?

RunAsync 的定义 - 这是在单独的 dll 中。

public static async Task RunAsync(string message)
{
    var mqttClient = factory.CreateMqttClient();
    //This creates MqttFactory and send message to all subscribers
    try
    {
        await mqttClient.ConnectAsync(options);        
    }
    catch (Exception exception)
    {
        Console.WriteLine("### CONNECTING FAILED ###" + Environment.NewLine + exception);
        throw exception;
    }
}

还有

Task<MqttClientConnectResult> ConnectAsync(IMqttClientOptions options)

【问题讨论】:

  • 刚开始时不要使用async void,如果每次有人使用async void 时微软都可以按下按钮来伤害编码器。事实上,我相信大多数 SO 用户也会这样做。
  • 还有什么是 RunAsync()?
  • RunAsync 是一个方法名。它可以是任何名称。有更好的解决方案吗?
  • 向我们展示该方法的定义,不要发表评论:)
  • @TheGeneral async void 仅允许在事件方法上使用。否则是的,使用该死的async Task

标签: c# multithreading asynchronous exception-handling async-await


【解决方案1】:

这是使用async void 的缺点。更改您的方法以返回 async Task

private async static Task MethodWithParameter(string message)
{
    try
    {
        await MQTTPublisher.RunAsync(message);

    }
    catch (Exception Ex)    
    {

    }            
}

基于:Async/Await - Best Practices in Asynchronous Programming

Async void 方法具有不同的错误处理语义。当异步任务或异步任务方法抛出异常时,会捕获该异常并将其放置在任务对象上。对于 async void 方法,没有 Task 对象,因此任何从 async void 方法抛出的异常都将直接在 async void 方法启动时处于活动状态的 SynchronizationContext 上引发。

还有:

图 2 来自 Async Void 方法的异常不能被 Catch 捕获

private async void ThrowExceptionAsync()
{
    throw new InvalidOperationException();
}

public void AsyncVoidExceptions_CannotBeCaughtByCatch()
{
    try
    {
        ThrowExceptionAsync();
    }
    catch (Exception)
    {
        // The exception is never caught here!
        throw;
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-08-19
    • 1970-01-01
    • 1970-01-01
    • 2019-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-12
    相关资源
    最近更新 更多