如何在.NET 4.5中“同时”运行这两个方法?

gz5pxeao  于 2022-12-27  发布在  .NET
关注(0)|答案(5)|浏览(153)

我有一个方法,做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)方法,但我不确定如何 * 设置 * 任务同时运行。
有什么建议吗,好心的朋友?

mccptt67

mccptt671#

以下是您可能需要执行的操作:

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 =等待c任务;变量food =等待fTask;
还有这个

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

这两种方法都将产生类似的结果,即先完成2个async任务,然后再完成return new PewPew-但是,不同之处在于Task.WaitAll()将阻塞当前线程(如果是UI线程,则UI将冻结)。相反,await将在状态机中分解SomeMethod,并在遇到await关键字时从SomeMethod返回到其调用方。它不会阻塞线程。await下面的代码将被安排在async任务结束时运行。
1.您还可以执行以下操作:
var cats =等待任务运行(()=〉获取所有猫(foo)); var food =等待任务.运行(()=〉获取所有食物(foo));
但是,这不会同时启动async任务。第二个任务将在第一个任务结束后启动。这是因为await关键字的工作原理。
编辑:如何使用SomeMethod-在调用树的开始,你必须使用Wait()Result属性-或者-你必须从async voidawait。通常,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);
}
6ljaweal

6ljaweal2#

到目前为止,最简单的方法是使用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()处理系统中处理器数量的扩展,但只有当您启动的不仅仅是几个任务时,这才真正重要。

7cjasjjr

7cjasjjr3#

如果您没有使用异步方法或者您使用的是旧版本的.Net framework,则不必使用异步。为简单起见,只需使用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
hm2xizp9

hm2xizp94#

您可以使用TPL来等待多个正在运行的任务。请参阅here
就像这样:

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
               };
}
rqqzpn5f

rqqzpn5f5#

再加上其他的答案,你可以这样做:

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>();
}

相关问题