WCFプロジェクトでコールバックを使用すると、いくつかの問題が発生します。
まず、サーバーはFoo
クライアントで関数を呼び出し、クライアントは要求をWindowsフォームGUIに転送します。
GUIクラス
delegate void DoForward();
public void ForwardToGui() {
if (this.cmdSomeButton.InvokeRequired) {
DoForward d = new DoForward(ForwardToGui);
this.Invoke(d);
}
else {
Process(); // sets result variable in callback class as soon as done
}
}
}
コールバッククラス
object _m = new object();
private int _result;
public int result {
get { return _result; }
set {
_result = value;
lock(_m) {
Monitor.PulseAll(_m);
}
}
}
[OperationContract]
public int Foo() {
result = 0;
Program.Gui.ForwardToGui();
lock(_m) {
Monitor.Wait(_m, 30000);
}
return result;
}
ここでの問題は、ユーザーがプロセスをキャンセルできる必要があることです。これは正しく機能しません。
サーバーインターフェイス
[OperationContract]
void Cleanup();
GUIクラス
private void Gui_FormClosed(object sender, EventArgs e) {
Program.callbackclass.nextAction = -1;
// so that the monitor pulses and Foo() returns
Program.server.Cleanup();
}
これに伴う問題は、Cleanup()
ハングすることです。ただし、実行していないときにフォームを閉じると、Process()
正しく機能します。
ソースはCleanup()
、モニターのパルスなどの前に呼び出されたため、サーバーからの最後の要求がまだ応答されていない前に、新しい要求がサーバーに送信されたようです。
どうすればこの問題を解決できますか?Cleanup()
呼び出す前に、noFoo()
が現在実行されていることを確認するにはどうすればよいですか?