c# - 来自 C# 任务的通用回调

标签 c# callback task-parallel-library async-await

async Task 调用通用回调的推荐方法是什么?例如,进度、异常处理和完成(但可以是其他状态)。

下面的代码展示了一种实现它的方法,但感觉应该有一种更简洁的方法来处理它。 (FWIW 我见过很多使用 ContinueWith 作为完成回调的示例,但这并没有真正处理其他情况,例如进度和异常处理)。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Testcode
{
    class TestApp
    {
        public static void Main()
        {
            AsyncCallbackTest test = new AsyncCallbackTest();
            test.RunTest();
        }
    }

    interface ICallback
    {
        void onProgress(String status);
        void onCompleted();
        void onFaulted(Exception e);
    }

    class AsyncCallbackTest : ICallback
    {

        public void RunTest()
        {
            //run task in background
            Task task = new Task(new Action<Object>(ExampleTask), this);
            task.Start();

            //do something else here
            //...

            //wait for task completion
            task.Wait();
        }

        public void onProgress(string status)
        {
            Console.Out.WriteLine(status);
        }

        public void onCompleted()
        {
            Console.Out.WriteLine("COMPLETED");
        }

        public void onFaulted(Exception e)
        {
            Console.Out.WriteLine("EXCEPTION: " + e.Message);
        }

        private void ExampleTask(object ocb)
        {
            ICallback callback = ocb as ICallback;

            //do some work
            try
            {
                DoSomething(callback);
            }
            catch (Exception e)
            {
                //how to pass exceptions/errors?
                callback.onFaulted(e);
            }
        }

        //example long-running task
        private void DoSomething(ICallback callback)
        {
            callback.onProgress("Starting");
            Thread.Sleep(5000);
            callback.onProgress("Step 1 complete");
            Thread.Sleep(5000);
            callback.onProgress("Step 2 complete");
            Thread.Sleep(5000);
            callback.onCompleted();
        }
    }
}

最佳答案

使用 async-await 完成和异常处理非常容易。进度处理正是 IProgress 接口(interface)的用途。

所以你的方法的签名应该是这样的:

public Task DoSomething(IProgress<string> progress = null);

你会这样调用它:

try
{
    await DoSomething(new Progress<string>(status => Console.WriteLine(status)));
    Console.WriteLine("COMPLETED");
}
catch (Exception e)
{
    Console.WriteLine("EXCEPTION: " + e.Message);
}

如果您不能使用 C# 5.0,那么您可以使用 ContinueWith() 而不是 await 并且您必须编写自己的 IProgress进度:

DoSomething(new Progress<string>(status => Console.WriteLine(status)))
    .ContinueWith(t =>
        {
            if (t.Exception != null)
                Console.WriteLine("EXCEPTION: " + t.Exception.InnerException.Message);
            else
                Console.WriteLine("COMPLETED");
        });

关于c# - 来自 C# 任务的通用回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20798335/

相关文章:

c# - 在使用 TPL 的非常密集的应用程序中,将异步套接字并行化,而不仅仅是并发化

c# - 是否存在链式 NULL 检查之类的东西?

c++ - 为什么功能没有完全执行?

c# - 主线程的 SynchronizationContext.Current 如何在 Windows 窗体应用程序中变为 null?

c - 为什么返回 float 的函数不适用于 void* 回调?

javascript - 回调 : animate complete: called after . Promise().done()

c# - 从特定线程调用方法

c# - .Result 或在 Task.WhenAll 之后等待

c# - 切换 HDMI 显示器时启动应用程序

c# - 如何使用 C# ASP.NET Core 应用程序通过 Elastic Beanstalk 设置对特定文件夹的权限?