2

別のアプリケーションドメインにある機能を使用する必要があります。結果はユーザーコントロールに表示されます。

私はそのようなものを持っています:

var instance = domain.CreateInstanceFromAndUnwrap(...);
instance.Foo(myWpfUserControl as ICallback);

Foo(ICallback itf) {
   itf.SetData("...");
}

WpfUserControl.SetData(string data)
{
   if (!Dispatcher.CheckAccess())
     Dispatcher.Invoke(...)
   ...
}  

[Serializable]属性をWpfUserControllクラスに配置し、シリアル化コンストラクターとISerializableインターフェイスを実装する必要がありましたが、例外が発生します。

The calling thread must be STA because many UI components require this 

これはUserControl()コンストラクターから発生します

これを避けるために私は何をすべきですか?前もって感謝します !

==============================

解決

@Alが気付いたように、クロスアプリケーションドメイン呼び出しに関しては、ユーザーコントロールをシリアル化する必要があります。ここで、ICallbackインターフェイスを実装するプロキシを渡します。プロキシはSerializable属性でマークされました。

ユーザー制御インスタンスをもう一度逆シリアル化する試みがあるはずなので、プロキシの実装にはユーザー制御に関する知識がまったくないはずです。インターフェイスを介してユーザーコントロールからプロキシを抽象化しようとしたとき、それは役に立ちませんでした。インターフェイスをプロキシに渡そうとすると(ユーザーコントロールによって実装されました)、同じ例外が発生しました。

最後に、プロキシとユーザー制御をキュー/セマフォで切り離しました。キューは、ユーザー制御への呼び出しを委任したワーカースレッドによって監視されました

psこのキューは「MarshalByObjectRef」から継承する必要があります。

4

1 に答える 1

2

例外がコンストラクターから発生している場合は、UIスレッドからこのコントロールインスタンスを作成していないことを意味します。.SetApartmentState(ApartmentState.STA)これは問題ない場合がありますが、スレッドを開始する前にスレッドオブジェクトを呼び出して、スレッドがSTAスレッドであることを確認する必要があります。

これは、スレッドプールスレッドでこれを行うことができないように、開始する前にスレッドオブジェクトにアクセスする必要があることも意味します。

ただし、この問題を回避する最善の方法は、メインUIスレッドでコントロールを作成してから、ディスパッチャー(またはUiSchedulerのタスク)を使用してテキスト値を割り当てることです。そうすれば、メインスレッドがコントロールを設定、取得、またはバインドする必要がある場合の問題も回避できます。これは、コントロールが別のスレッドで作成された場合にクロススレッド例外が発生するためです。

可能であれば、この方法でコントロールをシリアル化することはお勧めしません。これを行うと、パネルなどにアタッチされていない新しいオブジェクトが生成され、元のコントロールは更新されません。残念ながら、他のドメインへの参照のみを渡すため、シリアル化を排除するMarshalByRefObjectからの継承はできません。

可能であれば、Fooを個別に呼び出してから、結果を元のAppdomainのSetDataに渡します。

于 2011-05-26T08:36:38.517 に答える