41

私のWPFアプリケーションでは、(サーバーとの)非同期通信を行います。コールバック関数では、サーバーからの結果からInkPresenterオブジェクトを作成することになります。これには、実行中のスレッドがSTAである必要がありますが、現在はそうではないようです。したがって、次の例外が発生します。

アセンブリで定義された「InkPresenter」のインスタンスを作成できません[..]多くのUIコンポーネントがこれを必要とするため、呼び出し元のスレッドはSTAである必要があります。

現在、私の非同期関数呼び出しは次のようになっています。

public void SearchForFooAsync(string searchString)
{
    var caller = new Func<string, Foo>(_patientProxy.SearchForFoo);
    caller.BeginInvoke(searchString, new AsyncCallback(SearchForFooCallbackMethod), null);
}

InkPresenterの作成を行うコールバックをSTAにするにはどうすればよいですか?または、新しいSTAスレッドでXamlReader解析を呼び出します。

public void SearchForFooCallbackMethod(IAsyncResult ar)
{
    var foo = GetFooFromAsyncResult(ar); 
    var inkPresenter = XamlReader.Parse(foo.Xaml) as InkPresenter; // <!-- Requires STA
    [..]
}
4

5 に答える 5

59

次のようにSTAスレッドを開始できます。

    Thread thread = new Thread(MethodWhichRequiresSTA);
    thread.SetApartmentState(ApartmentState.STA); //Set the thread to STA
    thread.Start(); 
    thread.Join(); //Wait for the thread to end

唯一の問題は、結果オブジェクトを何らかの方法で渡す必要があることです。そのためにプライベートフィールドを使用するか、パラメータをスレッドに渡すことに飛び込むことができます。ここでは、fooデータをプライベートフィールドに設定し、STAスレッドを起動してinkpresenterを変更します。

private var foo;
public void SearchForFooCallbackMethod(IAsyncResult ar)
{
    foo = GetFooFromAsyncResult(ar); 
    Thread thread = new Thread(ProcessInkPresenter);
    thread.SetApartmentState(ApartmentState.STA);
    thread.Start();
    thread.Join(); 
}

private void ProcessInkPresenter()
{
    var inkPresenter = XamlReader.Parse(foo.Xaml) as InkPresenter;
}

お役に立てれば!

于 2010-03-04T09:26:43.037 に答える
12

Dispatcherクラスを使用して、UIスレッドでメソッド呼び出しを実行できます。Dispatcherは、スレッドのディスパッチャーを取得するための静的プロパティCurrentDispatcherを提供します。

InkPresenterを作成するクラスのオブジェクトがUIスレッドで作成されている場合、CurrentDispatcherメソッドはUIスレッドのディスパッチャーを返します。

Dispatcherでは、BeginInvokeメソッドを呼び出して、指定されたデリゲートをスレッド上で非同期的に呼び出すことができます。

于 2010-03-04T09:34:36.703 に答える
3

UIスレッドで呼び出すのに十分なはずです。したがって、BackgroundWorkerとを使用してRunWorkerAsyncCompleted、inkPresenterの作成を行うことができます。

于 2010-03-04T09:19:56.427 に答える
1

ちょっとしたハックですが、XTATestRunnerを使用するので、コードは次のようになります。

    public void SearchForFooAsync(string searchString)
    {
        var caller = new Func<string, Foo>(_patientProxy.SearchForFoo);
        caller.BeginInvoke(searchString, new AsyncCallback(SearchForFooCallbackMethod), null);
    }

    public void SearchForFooCallbackMethod(IAsyncResult ar)
    {
        var foo = GetFooFromAsyncResult(ar); 
        InkPresenter inkPresenter;
        new XTATestRunner().RunSTA(() => {
            inkPresenter = XamlReader.Parse(foo.Xaml) as InkPresenter;
        });
    }

ボーナスとして、次のようにSTA(またはMTA)スレッドでスローされた例外をキャッチすることができます。

try
{
    new XTATestRunner().RunSTA(() => {
        throw new InvalidOperationException();
    });
}
catch (InvalidOperationException ex)
{
}
于 2013-08-16T18:00:24.030 に答える
1

以下を使用して、STAスレッドからクリップボードのコンテンツを取得しました。将来誰かを助けるために投稿すると思いました...

string clipContent = null;
Thread t = new Thread(
    () =>
    {
        clipContent = Clipboard.GetText();
    });
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();

// do stuff with clipContent

t.Abort();
于 2019-06-18T12:26:48.343 に答える