views:

34

answers:

1

I am experiencing some issues when using a Callback in a WCF project.

First, the server invokes some function Foo on the client which then forwards the request to a Windows Forms GUI:

GUI CLASS

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
        }
    }
}

CALLBACK CLASS

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;
}

The problem now is that the user should be able to cancel the process, which doesn't work properly:

SERVER INTERFACE

[OperationContract]
void Cleanup();

GUI CLASS

private void Gui_FormClosed(object sender, EventArgs e) {
    Program.callbackclass.nextAction = -1; 
    // so that the monitor pulses and Foo() returns
    Program.server.Cleanup();
}

The problem with this is that Cleanup() hangs. However, when I close the form when Process() is not running, it works properly.

The source seems to be that the Cleanup() is called before the monitor pulses etc and therefore a new request is sent to the server before the last request from the server has not yet been responded.

How can I solve this problem? How can I ensure before calling Cleanup() that no Foo() is currently being executed?

A: 

The first warning I'm seeing is that you're calling Invoke instead of BeginInvoke

Invoke waits until the action has been completed on the other thread before returning, which can result in a deadlock in some situations.

Andrew Shepherd