【发布时间】:2015-06-30 01:43:58
【问题描述】:
我如何优雅地告诉我的应用程序它应该等待某个异步 (Ask()) 方法的结果,而不是在其当前 (Game) 线程上而是在不同的 ( UI) 线程?
我有一个带有两个线程的表单应用程序
- 强制
UI Thread,运行用户界面 - 还有第二个
Game Thread,它以一种无限循环的形式运行,等待输入操作并以或多或少恒定的帧速率渲染游戏视图。
用户界面由两种形式组成:
- 一个简单的
MainForm,带有一个Create Cube按钮、一个Create Sphere按钮和一个渲染视图 - 还有一个自定义的
ChoiceForm,它要求用户使用两个相应的按钮在Sharp Corners和Rounded Corners之间进行选择。
当用户单击Create Cube 按钮时,UI Thread 将处理此单击事件并(同步)将新的()=>Game.Create<Cube>() 操作排队以由Game Thread 处理。
Game Thread 将在处理另一个帧时获取此操作,并检查用户是否要创建 Cube 或 Sphere。如果用户请求Cube,它应该使用第二种形式询问用户所需的立体角形状。
问题是,在等待用户决定时,UI 和 Game 线程都不应该被阻塞。因此,Task Game.Create<T>(...) 方法和Task<CornerChoice> ChoiceForm.Ask()methods 被声明为异步。 Game Thread 将等待Create<T>() 方法的结果,而该方法又应该在UI 线程上等待Ask() 方法的结果(因为ChoiceForm 是在该方法内部创建并显示的)。
如果这一切都发生在一个 UI Thread 上,生活会相对容易,Create 方法看起来像这样:
public class Game
{
private async Task Create<IShape>()
{
CornerChoice choice = await ChoiceForm.Ask();
...
}
}
经过反复试验,我想出了以下(实际可行的)解决方案,但每次我仔细观察它时,它似乎都会伤害到我内心的某个地方(尤其是 Create 方法中的 Task<Task<CornerChoice>> 部分):
public enum CornerChoice {...}
public class ChoiceForm
{
public static Task<CornerChoice> Ask()
{
...
}
}
public class MainForm
{
private readonly Game _game;
public MainForm()
{
_game = new Game(TaskScheduler.FromCurrentSynchronizationContext());
}
...
}
public class Game
{
private readonly TaskScheduler _uiScheduler;
public Game(TaskScheduler uiScheduler)
{
_uiScheduler = uiScheduler;
}
private async Task Create<IShape>()
{
...
Task<CornerChoice> task = await Task<Task<CornerChoice>>.Factory.StartNew(
async () => await ChoiceForm.Ask(),
CancellationToken.None, TaskCreationOptions.None, _uiScheduler);
CornerChoice choice = await task;
...
}
}
【问题讨论】:
-
你的问题是什么?
-
有没有比我使用 await await Task
> 在不同线程上等待任务更好的方法? -
为什么游戏需要了解有关 UI 的任何信息?如果你想让它创建一个
Shape,你需要在用户告诉你他想要一个立方体还是一个球体之后告诉他(你的Game对象)。 -
@YuvalItzchakov 实际应用程序不是游戏,而是具有常规用户界面和一个或多个由第二个线程运行的渲染视图的应用程序。因为并不总是立即清楚,需要哪些进一步的步骤来完成这样的“创建”请求,所以第二个(视口)线程需要有可能向用户呈现额外的问题并等待他们的结果,而不会中断渲染过程。
-
你可以尝试用Task.Run替换Task.Factory.StartNew吗,在这种情况下你不需要创建像Task
>这样的类型,我将粘贴一个我有的简单示例在下面创建。它可能无法回答您的完整问题,但试图解决问题的子部分
标签: c# multithreading asynchronous async-await task