异步方法是否通过委托回调以正确的方式调用策略?

时间:2017-06-01 13:31:02

标签: c# multithreading asynchronous

当我想让一个方法可以同步和异步访问,然后我将它包装在Thread内并通过委托回调返回结果。

这是一个好策略还是一种非常糟糕的编程方式?

public delegate void FooDelegate(bool foo);

public bool FooMethod()
{
    //snychron operation
    return true;
}

public void FooMethodAsync(FooDelegate fooDelegate)
{
    ThreadStart fooThreadStart = () =>
    {
        fooDelegate?.Invoke(FooMethod());
    };
    Thread fooThreadStartThread = new Thread(fooThreadStart) { IsBackground = true };
    fooThreadStartThread.Start();            
}

调用方法:

FooClass fooClass = new FooClass();

//Call Synchron
var fooResult = fooClass.Disconnect();

//Call with Callback async
fooClass.DisconnectAsync(ResultCallback);


private static void ResultCallback(bool foo)
{

}

修改

这是一个很好的阅读:

3 个答案:

答案 0 :(得分:3)

不,这不是一个好的模式。当异步实现本质上异步(并且同步实现本质上是同步的)时,您应该只为操作公开同步和异步方法,而不是简单地调用同步实现新线程或线程池线程。 (有时可以在对象需要实现提供同步和异步实现的接口的情况下进行异常,即使只有一个有意义。)如果调用者想要在新线程或线程中异步执行同步操作池线程,他们可以在必要的情况下自己轻松完成。这也更有效地传达了正在发生的事情。如果调用者看到异步方法,他们就会认为该操作本身异步异步,这在您的情况下是错误的假设。

此外,使用基于回调的模型不再被认为是一种好习惯。相反,使用基于任务的模型,其中异步方法返回Task,它本身可用于添加在异步操作完成时运行的延续,以及提供许多其他功能。

答案 1 :(得分:0)

public void FooMethodAsync(FooDelegate fooDelegate)
{
    Task.Run(() => {
        var result = FooMethod();
        fooDelegate(result);
    });
}

此方法对异常不稳定。 Task.Run会立即结束,但如果在FooMethodfooDelegate内引发异常,您的申请将会中止。它没那么好,但你可以忽略这些例外:

public void FooMethodAsync(FooDelegate fooDelegate)
{
    Task.Run(() => {
        try
        {
            var result = FooMethod();
            fooDelegate(result);
        }
        catch
        {
            // Who cares?
        }
    });
}

答案 2 :(得分:-1)

不,这不是方法。您应该使用TaskTask<T>类作为返回类型,并在方法中使用Task.Run()来调用线程池线程中的操作,这称为&#34;基于任务的异步模式& #34 ;.

internal Task<Bitmap> RenderAsync(
                 ImageData data, CancellationToken cancellationToken)
   {
       return Task.Run(() =>
       {
           var bmp = new Bitmap(data.Width, data.Height);
           for(int y=0; y<data.Height; y++)
           {
               cancellationToken.ThrowIfCancellationRequested();
               for(int x=0; x<data.Width; x++)
               {
                   // render pixel [x,y] into bmp
               }
           }
           return bmp;
       }, cancellationToken);
   }

此外,您的方法必须具有async关键字才能从异步代码中调用。

更多信息:

https://msdn.microsoft.com/en-us/library/hh873177(v=vs.110).aspx