我正在尝试在任务上设置公寓状态,但在执行此操作时看不到任何选项。有没有办法使用任务执行此操作?
for (int i = 0; i < zom.Count; i++)
{
Task t = Task.Factory.StartNew(zom[i].Process);
t.Wait();
}
答案 0 :(得分:83)
当StartNew
失败时,您只需自己动手:
public static Task<T> StartSTATask<T>(Func<T> func)
{
var tcs = new TaskCompletionSource<T>();
Thread thread = new Thread(() =>
{
try
{
tcs.SetResult(func());
}
catch (Exception e)
{
tcs.SetException(e);
}
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return tcs.Task;
}
(您可以为Task
创建一个看起来几乎相同的,或为StartNew
的各种选项添加重载。)
答案 1 :(得分:14)
Servy对启动虚拟任务的回答超载
public static Task StartSTATask(Action func)
{
var tcs = new TaskCompletionSource<object>();
var thread = new Thread(() =>
{
try
{
func();
tcs.SetResult(null);
}
catch (Exception e)
{
tcs.SetException(e);
}
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return tcs.Task;
}
答案 2 :(得分:12)
您可以按照以下方式创建新任务:
try
{
Task reportTask = Task.Factory.StartNew(
() =>
{
Report report = new Report(this._manager);
report.ExporterPDF();
}
, CancellationToken.None
, TaskCreationOptions.None
, TaskScheduler.FromCurrentSynchronizationContext()
);
reportTask.Wait();
}
catch (AggregateException ex)
{
foreach(var exception in ex.InnerExceptions)
{
throw ex.InnerException;
}
}
答案 3 :(得分:1)
这是Task
构造函数和RunSynchronously
方法的好用例。
public static Task<T> RunSTATask<T>(Func<T> function)
{
var task = new Task<T>(function, TaskCreationOptions.DenyChildAttach);
var thread = new Thread(task.RunSynchronously);
thread.IsBackground = true;
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return task;
}
TaskCreationOptions.DenyChildAttach
的目的是使所得任务的行为与Servy的solution相同(不可能将子任务附加到父TaskCompletionSource.Task
)。 Task.Run
方法的行为也是拒绝孩子的依恋。
答案 4 :(得分:0)
如果需要为Task提供一个CancellationToken,则可以在任务操作中启动STA线程并按如下所示加入STA线程:
var task = Task.Factory.StartNew(() =>
{
var tcs = new TaskCompletionSource<object>();
var thread = new Thread(() =>
{
try
{
action();
tcs.SetResult(new object());
}
catch (Exception e)
{
tcs.SetException(e);
}
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join();
}, cancellationToken);
答案 5 :(得分:-1)
这是我与Action一起使用的原因,因为我不需要返回任何内容:
public static class TaskUtil
{
public static Task StartSTATask(Action action)
{
var tcs = new TaskCompletionSource<object>();
var thread = new Thread(() =>
{
try
{
action();
tcs.SetResult(new object());
}
catch (Exception e)
{
tcs.SetException(e);
}
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return tcs.Task;
}
}
在这里我这样称呼它:
TaskUtil.StartSTATask(async () => await RefreshRecords());
有关详细信息,请参见https://github.com/xunit/xunit/issues/103和Func vs. Action vs. Predicate
仅供参考,这是我需要设置公寓状态的例外情况:
发生System.InvalidOperationException HResult = -2146233079
Message =调用线程必须是STA,因为许多UI组件 要求这个。来源= PresentationCore StackTrace: 在System.Windows.Input.InputManager..ctor() 在System.Windows.Input.InputManager.GetCurrentInputManagerImpl() 在System.Windows.Input.Keyboard.ClearFocus()