在C#中从非异步调用异步代码的最佳方法是什么(Fire和Forget)

时间:2017-10-04 00:13:03

标签: c# asp.net-mvc asynchronous task-parallel-library

  

尝试实现Fire并忘记:

class Program
{
    static void Main(string[] args)
    {
       var my = new MyClass();

       my.OrderForm_Load();
       Console.ReadLine();
    }

}

internal class MyClass
{
    //Blocking
    public void OrderForm_Load()
    {
        var t1 = new ServiceTask();

        Task.Run(() => t1.PersistTask()); //Approach 1:
        //[OR]            
        t1.PersistTask(); //Approach 2: Has compiler errors CS4014
        Console.WriteLine("Second");
    }
}

internal class ServiceTask
{
    //Non-Blocking
    public async Task PersistTask()
    {
        var resultTask = Task.Run(() =>
        {
            Thread.Sleep(3000);
            Console.WriteLine("First");
            return Task.FromResult(0);
        });

        await resultTask;
    }
}

在方法1和方法2之间;我更喜欢方法1.还有其他更好的方法从OrderForm_Load()方法调用PersistTask()吗?我有一位同事在使用Task.Run时犹豫不决,但想知道是否还有其他更好的方法。

目标是,我们想要"第二"尽快打印,不用担心打印的方法"首先"。火与忘记。

1 个答案:

答案 0 :(得分:3)

实现fire and forget方法的最佳方法是使用async void修饰符:

public async void PersistTask()
{
    // no need to assign the task if you are just going to await for it.
    await Task.Run(() =>
    {
        Thread.Sleep(3000);
        Console.WriteLine("First");
        return Task.FromResult(0);
    });
}

并使用以下方式调用它:

//Blocking
public void OrderForm_Load()
{
    var t1 = new ServiceTask();

    Task.Run(() => t1.PersistTask()); //Approach 1
    //[OR]            
    t1.PersistTask(); //Approach 2
    Console.WriteLine("Second");
}

但是还有另一个区别:Task.Run最适合CPU绑定方法。查看更多详情in this answer 另请注意,应避免在异步工作中使用同步等待。所以,改变这个:

Thread.Sleep(3000);

为此:

Task.Delay(3000);