我在下面编写了一个断言方法Ensure.CurrentlyOnUiThread(),用于检查当前线程是否为UI线程.
Ensure.cs
using System.Diagnostics;
using System.Windows.Forms;
public static class Ensure
{
[Conditional("DEBUG")]
public static void CurrentlyOnUiThread()
{
if (!Application.MessageLoop)
{
throw new ThreadStateException("Assertion failed: not on the UI thread");
}
}
}
Run Code Online (Sandbox Code Playgroud) 我一直在试图追查了以下问题的WinForms应用程序:
本SynchronizationContext.Current是一个任务的延续(即空.ContinueWith这是主要的线程上运行)(我预计当前同步上下文是System.Windows.Forms.WindowsFormsSynchronizationContext).
以下是演示此问题的Winforms代码:
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
TaskScheduler ts = TaskScheduler.FromCurrentSynchronizationContext(); // Get the UI task scheduler
// This line is required to see the issue (Removing this causes the problem to go away), since it changes the codeflow in
// \SymbolCache\src\source\.NET\4\DEVDIV_TFS\Dev10\Releases\RTMRel\ndp\clr\src\BCL\System\Threading\ExecutionContext.cs\1305376\ExecutionContext.cs
// at line 435
System.Diagnostics.Trace.CorrelationManager.StartLogicalOperation("LogicalOperation");
var task = Task.Factory.StartNew(() => { });
var cont …Run Code Online (Sandbox Code Playgroud) 我开发了一个Outlook VSTO插件.某些任务应该在后台线程上完成.通常,检查本地数据库中的某些内容或调用Web请求.阅读了几篇文章之后,我放弃了在后台线程中调用Outlook对象模型(OOM)的想法.
我有一些wpf控件,我成功地设法使用.NET 40 TPL执行异步任务,并在完成时"完成"主VSTA线程中的作业(即访问UI或OOM).
为此,我使用了以下形式的语法:
Task<SomeResult> task = Task.Factory.StartNew(()=>{
//Do long tasks that have nothing to do with UI or OOM
return SomeResult();
});
//now I need to access the OOM
task.ContinueWith((Task<SomeResult> tsk) =>{
//Do something clever using SomeResult that uses the OOM
},TaskScheduler.FromCurrentSynchronizationContext());
Run Code Online (Sandbox Code Playgroud)
到现在为止还挺好.但现在我想在OOM中挂钩没有Form/WPF控件的事件时做类似的事情.确切地说,我的问题来自于TaskScheduler.FromCurrentSynchronizationContext()抛出异常的事实.
例如,
Items inboxItems = ...;
inboxItems.ItemAdd += AddNewInboxItems;
private void AddNewInboxItems(object item)
{
Task<SomeResult> task = Task.Factory.StartNew(()=>{
//Do long tasks that have nothing to do with OOM
return SomeResult()});
var scheduler = …Run Code Online (Sandbox Code Playgroud) .NET 4.5是就地升级,因此取代了.NET 4.0.因此,当我使用Visual Studio 2012安装.NET 4.5时,我无法再为.NET 4.0开发应用程序.
由于Windows XP不支持.NET 4.5,如何在安装Visual Studio 2012后维护现有的.NET 4.0应用程序仍然必须在Windows XP下运行?
到目前为止,只要安装了VS2003,我就可以为每个版本甚至.NET 1.1开发.NET应用程序.我没有问题微软不支持XP上的.NET 4.5,我认为切断旧东西是可以的.但是,由于我们仍然有客户使用Windows XP,我们需要能够在.NET 4.5的同时创建.NET 4.0程序.
编辑:
我刚刚遇到了第一个不兼容问题:我在Windows Server 2012上安装了VS 2012.我创建了一个面向.NET 4.0的项目.在blend 4.0中,我创建了一个复选框的控件模板的副本.生成的模板包含仅在.NET 4.5下可用的颜色的引用.解决方案无法再编译.但是,同样的情况在我的Windows 7安装上运行正常.
我假设.NET 4.5的安装已经取代了我的标准控件的控件模板.因此我不能再创建副本了.
我创建了一个TaskScheduler,我将它作为两个不同任务的参数传递.
这样做有什么问题吗?我应该为每个任务创建一个新的TaskScheduler实例吗?
这是示例示例(为简单起见,每个任务中的实际代码都被删除)
var uiSch = System.Threading.Tasks.TaskScheduler.FromCurrentSynchronizationContext();
var t1 = Task.Factory.StartNew<List<Carrier>>(() =>
{
//does stuff
})
.ContinueWith(previous =>
{
//does stuff
},
System.Threading.CancellationToken.None,
TaskContinuationOptions.OnlyOnRanToCompletion,
uiSch);
var t2 = Task.Factory.StartNew<List<Logic.WarehouseLogic.Warehouse>>(() =>
{
//does stuff
})
.ContinueWith(previous =>
{
//does stuff
},
System.Threading.CancellationToken.None,
TaskContinuationOptions.OnlyOnRanToCompletion,
uiSch);
Run Code Online (Sandbox Code Playgroud)
[EDIT1]
我的问题部分与以下错误有关:'当前的SynchronizationContext可能不会被用作TaskScheduler'可在此处找到修复
c# ×4
winforms ×2
.net-4.0 ×1
.net-4.5 ×1
assertions ×1
outlook ×1
vsto ×1
windows-xp ×1
wpf ×1