如何同时运行这两个方法''在.net 4.5中

本文关键字:net 方法 两个 运行 何同时 | 更新日期: 2023-09-27 18:15:21

我有一个方法,它做2 独立的块逻辑。我希望我能同时运行它们 ..只有当这两个子方法都完成后才继续。

我试着去理解async/await的语法,但是我就是不明白。

代码如下:

public PewPew SomeMethod(Foo foo)
{
    var cats = GetAllTheCats(foo);
    var food = GetAllTheFood(foo);
    return new PewPew
               {
                   Cats = cats,
                   Food = food
               };
}
private IList<Cat> GetAllTheCats(Foo foo)
{
    // Do stuff, like hit the Db, spin around, dance, jump, etc...
    // It all takes some time.
    return cats;
}
private IList<Food> GetAllTheFood(Foo foo)
{
    // Do more stuff, like hit the Db, nom nom noms...
    // It all takes some time.
    return food;
}
所以对于上面的代码,我想说:去同时得到所有的猫和食物。一旦我们完成,然后返回一个新的PewPew

我很困惑,因为我不确定上面哪些类是async或返回Task等。所有人?只有两个私人的吗?我也猜我需要利用Task.WaitAll(tasks)方法,但我不确定如何设置任务同时运行。

亲爱的朋友们,有什么建议吗?

如何同时运行这两个方法''在.net 4.5中

你可以这样做:

public async Task<PewPew> SomeMethod(Foo foo)
{
    // get the stuff on another thread 
    var cTask = Task.Run(() => GetAllTheCats(foo));
    var fTask = Task.Run(() => GetAllTheFood(foo));
    var cats = await cTask;
    var food = await fTask;
    return new PewPew
               {
                   Cats = cats,
                   Food = food
               };
}
public IList<Cat> GetAllTheCats(Foo foo)
{
    // Do stuff, like hit the Db, spin around, dance, jump, etc...
    // It all takes some time.
    return cats;
}
public IList<Food> GetAllTheFood(Foo foo)
{
    // Do more stuff, like hit the Db, nom nom noms...
    // It all takes some time.
    return food;
}

这里有两件事你需要明白:

  1. 这两者有什么不同:

    var cats = await cTask;var food = await fTask;

:

Task.WaitAll(new [] {cTask, fTask});

两者都会给你类似的结果,让2个async任务完成,然后是return new PewPew -然而,不同的是Task.WaitAll()将阻塞当前线程(如果那是UI线程,那么UI将冻结)。相反,await将分解状态机中的SomeMethod语句,并在遇到await关键字时从SomeMethod返回给它的调用者。它不会阻塞线程。await以下的代码将在async任务结束时调度运行。

  • 你也可以这样做:

    var cats = await Task.Run(() =>GetAllTheCats (foo));var food = await Task.Run(() =>

    GetAllTheFood (foo));
  • 但是,这不会同时启动async任务。第一个任务结束后,第二个任务将开始。这是因为await关键字的工作方式。

    编辑:如何使用SomeMethod -在调用树开始的某个地方,您必须使用Wait()Result属性-或者-您必须从async void中使用await。通常,async void将是一个事件处理程序:

    public async void OnSomeEvent(object sender, EventArgs ez) 
    { 
      Foo f = GetFoo();
      PewPew p = await SomeMethod(f);
    }
    

    如果没有,则使用Result属性。

    public Foo2 NonAsyncNonVoidMethod() 
    {
       Foo f = GetFoo();
       PewPew p = SomeMethod(f).Result; //But be aware that Result will block thread
      
       return GetFoo2(p);
    }
    

    目前为止最简单的方法是使用Parallel.Invoke()

    IList<Cat> cats;
    IList<Food> food;
    Parallel.Invoke
    (
        () => cats = GetAllTheCats(foo),
        () => food = GetAllTheFood(foo)
    );
    

    Parallel.Invoke()将等待所有方法返回,然后它自己返回。

    更多信息在这里:http://msdn.microsoft.com/en-us/library/dd460705.aspx

    请注意,Parallel.Invoke()处理系统中处理器数量的缩放,但这只有在启动多个任务时才真正重要。

    如果你没有使用async方法,或者你使用的是旧版本的。net框架,你不必使用async。为了简单起见,只需使用Tasks:

    Task taskA = Task.Factory.StartNew(() => GetAllTheCats(foo));
    Task taskB = Task.Factory.StartNew(() => GetAllTheFood(foo));
    Task.WaitAll(new [] { taskA, taskB });
    // Will continue after both tasks completed
    

    您可以使用TPL等待多个正在运行的任务。看到这里。

    :

    public PewPew SomeMethod(Foo foo) {
        IList<Cat> cats = null;
        IList<Food> foods = null;
        Task[] tasks = new tasks[2] {
            Task.Factory.StartNew(() => { cats = GetAllTheCats(foo); }),
            Task.Factory.StartNew(() => { food = GetAllTheFood(foo); })
        };
        Task.WaitAll(tasks);
        return new PewPew
                   {
                       Cats = cats,
                       Food = food
                   };
    }
    

    添加到其他答案中,您可以这样做:

    public PewPew SomeMethod(Foo foo)
    {
        Task<IList<Cat>> catsTask = GetAllTheCatsAsync(foo);
        Task<IList<Food>> foodTask = GetAllTheFoodAsync(foo);
        // wait for both tasks to complete
        Task.WaitAll(catsTask, foodTask);
        return new PewPew
        {
            Cats = catsTask.Result,
            Food = foodTask.Result
        };
    }
    public async Task<IList<Cat>> GetAllTheCatsAsync(Foo foo)
    {
        await Task.Delay(7000); // wait for a while
        return new List<Cat>();
    }
    public async Task<IList<Food>> GetAllTheFoodAsync(Foo foo)
    {
        await Task.Delay(5000); // wait for a while
        return new List<Food>();
    }