0

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()が現在実行されていることを確認するにはどうすればよいですか?

4

1 に答える 1

0

最初に表示される警告は、 BeginInvokeではなく Invokeを呼び出していることです。

Invokeは、他のスレッドでアクションが完了するまで待ってから戻るため、状況によってはデッドロックが発生する可能性があります。

于 2010-05-27T00:46:35.360 に答える