我正在尝试在一项任务上设置公寓状态,但看不到这样做的选择。有没有办法使用任务来做到这一点?
for (int i = 0; i < zom.Count; i++)
{
Task t = Task.Factory.StartNew(zom[i].Process);
t.Wait();
}
我正在尝试在一项任务上设置公寓状态,但看不到这样做的选择。有没有办法使用任务来做到这一点?
for (int i = 0; i < zom.Count; i++)
{
Task t = Task.Factory.StartNew(zom[i].Process);
t.Wait();
}
失败时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
。)
Servy 启动 void 任务的答案超载
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;
}
例如,您可以按如下方式创建新任务:
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;
}
}
这是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 的解决方案相同(不可能将子任务附加到父任务TaskCompletionSource.Task
)。拒绝孩子依附也是Task.Run
方法的行为。
这是我在 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 组件都需要这个。Source=PresentationCore StackTrace:在 System.Windows.Input.InputManager..ctor() 在 System.Windows.Input.InputManager.GetCurrentInputManagerImpl() 在 System.Windows.Input.Keyboard.ClearFocus()