在任务上设置ApartmentState

Luk*_*101 39 c# task

我试图在任务上设置公寓状态但是看不到这样做的选项.有没有办法使用任务执行此操作?

for (int i = 0; i < zom.Count; i++)
{
     Task t = Task.Factory.StartNew(zom[i].Process);
     t.Wait();
}
Run Code Online (Sandbox Code Playgroud)

Ser*_*rvy 89

如果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;
}
Run Code Online (Sandbox Code Playgroud)

(你可以为Task它创建一个看起来几乎相同的,或为某些各种选项添加重载StartNew.)

  • 你不应该在try-catch之后添加一个`System.Windows.Threading.Dispatcher.CurrentDispatcher.InvokeShutdown()`来清理调度程序资源吗? (3认同)
  • 此代码将单元状态设置为 STA,但不执行泵操作,这是 STA 线程的要求。因此,有一个隐含的假设:“func”将进行泵送。小心使用。 (3认同)
  • 因此我的问题是"我个人需要它用于WPF - 所以在我的情况下我应该插入InvokeShutdown,对吧?".但是,谢谢你. (2认同)
  • @John您应该在创建它们的同一范围内清理资源。如果你在别处创建了一个调度程序,在那里清理它。 (2认同)

Dav*_*vid 15

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;
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢男人,我自己尝试过,但是失败了。 (2认同)

小智 13

例如,您可以按如下方式创建新任务:

       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;
            }
        }
Run Code Online (Sandbox Code Playgroud)

  • 这真的是公寓的状态!? (5认同)
  • 这只会抛出ex.InnerExceptions的第一个异常. (3认同)
  • 哦,我的兄弟!谢谢你这个片段!我花了最后2个小时寻找这个,因为即使我根据msdn实现了MessageFilter,我仍然得到那个frakking'busy'异常并且根本没有调用过滤器方法.一切都很好,直到我在普通的命令行中运行它,但后来我想要一些UI,以更方便的方式为解决方案生成提供参数,并在任务执行DTE的东西上进行UI的进度更新.地狱爆发了......谢谢! (2认同)

The*_*ias 5

Task这是构造函数和方法的一个很好的用例RunSynchronously

public static Task<T> RunSTATask<T>(Func<T> function)
{
    Task<T> task = new(function, TaskCreationOptions.DenyChildAttach);
    Thread thread = new(() => task.RunSynchronously());
    thread.IsBackground = true;
    thread.SetApartmentState(ApartmentState.STA);
    thread.Start();
    return task;
}
Run Code Online (Sandbox Code Playgroud)

的目的TaskCreationOptions.DenyChildAttach是使结果任务的行为与 Servy 的解决方案TaskCompletionSource.Task相同(不可能将子任务附加到父任务)。拒绝孩子依恋也是Task.Run方法的行为。