C# 确保在使用WCF通过双工通道发送新请求之前完成所有回调

C# 确保在使用WCF通过双工通道发送新请求之前完成所有回调,c#,wcf,winforms,duplex,C#,Wcf,Winforms,Duplex,我在WCF项目中使用回调时遇到一些问题 首先,服务器在客户端上调用一些函数Foo,然后将请求转发到Windows窗体GUI: GUI类 delegate void DoForward(); public void ForwardToGui() { if (this.cmdSomeButton.InvokeRequired) { DoForward d = new DoForward(ForwardToGui); this.Invoke(d);

我在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;
}
private void Gui_FormClosed(object sender, EventArgs e) {
    Program.callbackclass.nextAction = -1; 
    // so that the monitor pulses and Foo() returns
    Program.server.Cleanup();
}
回调类

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;
}
private void Gui_FormClosed(object sender, EventArgs e) {
    Program.callbackclass.nextAction = -1; 
    // so that the monitor pulses and Foo() returns
    Program.server.Cleanup();
}
现在的问题是,用户应该能够取消无法正常工作的流程:

服务器界面

[OperationContract]
void Cleanup();
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;
}
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()
之前,如何确保当前没有执行
Foo()

我看到的第一个警告是您正在调用而不是


Invoke在返回之前会等待另一个线程上的操作完成,这在某些情况下可能会导致死锁。

我在尝试将代码片段拼凑在一起时太困惑了。这两个代码段是否在同一个GUI类中标题为“GUI类”?我看到的第一个警告是,您正在调用System.Windows.Form.Invoke,而不是System.Windows.Forms.BeginInvoke。这是故意的吗?两个标有GUI类的部分是同一个类。我正在努力。看来是贝金诺克干的!谢谢:-)您介意再次发布您的评论作为答复吗?