代码之家  ›  专栏  ›  技术社区  ›  Etan bbum

确保在使用WCF通过DuplexChannel发送新请求之前完成所有回调

  •  0
  • Etan bbum  · 技术社区  · 14 年前

    在WCF项目中使用回调时遇到一些问题。

    首先,服务器调用一些函数 Foo 在将请求转发到Windows窗体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();
    

    图形用户界面类

    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() 没有运行,它工作正常。

    来源似乎是 清除() 在监视器脉冲等之前调用,因此在服务器的最后一个请求尚未响应之前,会向服务器发送一个新请求。

    我如何解决这个问题?打电话前我怎么保证 清除() 那没有 Foo() 当前正在执行?

    1 回复  |  直到 14 年前
        1
  •  0
  •   Andrew Shepherd    14 年前

    我看到的第一个警告是你打电话来 Invoke 而不是 BeginInvoke

    援引 等待另一个线程上的操作完成后再返回,这在某些情况下可能导致死锁。