Dan*_*ant 5 task-parallel-library
以下是一些显示意外行为的简单代码:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
_UI = TaskScheduler.FromCurrentSynchronizationContext();
Loaded += new RoutedEventHandler(MainWindow_Loaded);
}
TaskScheduler _UI;
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
Task.Factory.StartNew(() =>
{
//Expected: Worker thread
//Found: Worker thread
DoSomething();
})
.ContinueWith(t =>
{
//Expected: Main thread
//Found: Main thread
DoSomething();
Task.Factory.StartNew(() =>
{
//Expected: Worker thread
//Found: Main thread!!!
DoSomething();
});
}, _UI);
}
void DoSomething()
{
Debug.WriteLine(Thread.CurrentThread.ManagedThreadId.ToString());
}
}
Run Code Online (Sandbox Code Playgroud)
为什么内部任务在主线程中执行?我该如何防止这种行为?
不幸的是,当你正在运行你的延续时,当前的任务调度程序将成为SynchronizationContextTaskScheduler你的设置TaskScheduler.FromCurrentSynchronizationContext.
这是在讨论这个连接错误 -而写这样的设计在.NET 4.但是,我认为,行为极不期望在这里一点.
您可以通过在构造函数中抓取"后台"调度程序并使用它来解决此问题:
TaskScheduler _UI;
// Store the default scheduler up front
TaskScheduler _backgroundScheduler = TaskScheduler.Default;
public MainWindow()
{
InitializeComponent();
_UI = TaskScheduler.FromCurrentSynchronizationContext();
Loaded += new RoutedEventHandler(MainWindow_Loaded);
}
Run Code Online (Sandbox Code Playgroud)
完成后,您可以轻松地安排"背景"任务:
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
Task.Factory.StartNew(() =>
{
//Expected: Worker thread
//Found: Worker thread
DoSomething();
})
.ContinueWith(t =>
{
//Expected: Main thread
//Found: Main thread
DoSomething();
// Use the _backgroundScheduler here
Task.Factory.StartNew(() =>
{
DoSomething();
}, CancellationToken.None, TaskCreationOptions.None, _backgroundScheduler);
}, _UI);
}
Run Code Online (Sandbox Code Playgroud)
此外,在这种情况下,由于您的操作已结束,您可以将其置于自己的延续中并获得所需的行为.然而,这不是"通用"解决方案,但在这种情况下有效:
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
Task.Factory.StartNew(() =>
{
//Expected: Worker thread
//Found: Worker thread
DoSomething();
})
.ContinueWith(t =>
{
//Expected: Main thread
//Found: Main thread
DoSomething();
}, _UI)
.ContinueWith(t =>
{
//Expected: Worker thread
//Found: Is now worker thread
DoSomething();
});
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
489 次 |
| 最近记录: |