it-swarm.com.de

Legen Sie ApartmentState für eine Aufgabe fest

Ich versuche, den Apartmentstatus für eine Aufgabe festzulegen, sehe jedoch keine Möglichkeit, dies zu tun. Gibt es eine Möglichkeit, dies mit einer Aufgabe zu tun?

for (int i = 0; i < zom.Count; i++)
{
     Task t = Task.Factory.StartNew(zom[i].Process);
     t.Wait();
}
39
Luke101

Wenn StartNew fehlschlägt, machen Sie es einfach selbst:

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;
}

(Sie können eine für Task erstellen, die fast identisch aussieht, oder Überladungen für einige der verschiedenen Optionen hinzufügen, die StartNew hat.)

85
Servy

Eine Überlastung von Servys Antwort, um eine ungültige Aufgabe zu starten

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;
}
14
David

Sie können beispielsweise eine neue Aufgabe wie folgt erstellen:

       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;
            }
        }
13
BEN'S

Dies ist, was ich mit Action verwende, da ich nichts zurückgeben muss:

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;
    }
}

Wo ich es so nenne:

TaskUtil.StartSTATask(async () => await RefreshRecords());

Weitere Informationen finden Sie unter https://github.com/xunit/xunit/issues/1 und Func vs. Action vs. Predicate

Zu Ihrer Information, dies ist die Ausnahme, die ich erhalten habe, als ich den Apartmentstatus festlegen wollte:

System.InvalidOperationException aufgetreten HResult = -2146233079
Message = Der aufrufende Thread muss STA sein, da dies für viele UI-Komponenten erforderlich ist. Source = PresentationCore StackTrace: bei System.Windows.Input.InputManager..ctor () bei System.Windows.Input.InputManager.GetCurrentInputManagerImpl () bei System.Windows.Input.Keyboard.ClearFocus ()

1
user8128167