如何同时运行这两个方法''在.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)
方法,但我不确定如何设置任务同时运行。
你可以这样做:
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;
}
这里有两件事你需要明白:
这两者有什么不同:
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>();
}