tags:

views:

286

answers:

4

Hello,

C# 2008 SP1

The function below will be called from another thread. So the control themselves will have to be invoked so that the correct thread that created them can change the properties.

However, as I have many controls that need to be updated. I don't really want to write all those delegates for each one. I have done one below. However, I am thinking that is a lot of code. Is there anyway to shorten this?

Many thanks,

public void SetIdleState(string callStatusMsg)
    {
        this.btnCallAnswer.Text = CATWinSIP_MsgStrings.Call;
        this.btnEndCallReject.Text = CATWinSIP_MsgStrings.EndCall;
        this.btnHoldUnhold.Text = CATWinSIP_MsgStrings.Hold;

        this.btnCallAnswer.Enabled = true;
        this.btnRedial.Enabled = true;
        this.btnEndCallReject.Enabled = false;
        this.btnHoldUnhold.Enabled = false;

        if (this.statusDisplay1.InvokeRequired)
        {
            statusDisplay1.Invoke(new UpdateCallStatusDelegate(this.UpdateCallStatus), callStatusMsg);      
        }
        else
        {
           this.statusDisplay1.CallStatus = callStatusMsg;
        }
    }      

    // Delegate for marshalling the call on the correct thread.
    private delegate void UpdateCallStatusDelegate(string callStatusMsg);
    private void UpdateCallStatus(string callStatusMsg)
    {
        this.statusDisplay1.CallStatus = callStatusMsg;
    }
+1  A: 

How about something like:

Dispatcher.BeginInvoke(new DispatcherOperationCallback((param) =>

      {

           this.statusDisplay1.CallStatus = callStatusMsg;

          return null;

      }), DispatcherPriority.Background, new object[] { null });

    }
Sean Turner
Not sure if I explain myself. But I need to change all the controls in that function. For example I did one which was the statusDislay control to show how I was performing this. However, I don't want to write the same code like that for each other control. i.e. tbnCallNumber, btnEndCallReject, btnHoldUnhold etc.
robUK
+1  A: 

I asked a similar question . The answer that was provided by Jon Skeet is the best approach I have come across. The relevant code is below.

Create a static helper method:

public static void InvokeIfNecessary(UIElement element, MethodInvoker action)
{
    if (element.Dispatcher.Thread != Thread.CurrentThread)
    {
        element.Dispatcher.Invoke(DispatcherPriority.Normal, action);
    }
    else
    {
        action();
    }
}

In your example you could use it as:

InvokeIfNecessary(statusDisplay1, delegate {statusDisplay1.CallStatus = callStatusMsg;});
sipwiz
+1  A: 

Here is what I've done in a previous project:

I wrote a helper static class.

public static class WorkbenchService
{    
    private static SynchronizationContext uiContext;
static WorkbenchService()
{
    uiContext = WindowsFormsSynchronizationContext.Current;
}

/// <summary>
    /// Makes a call GUI threadSafe. WARNING: This method waits for the result of the operation, which can result in a dead-lock when the main thread waits for this thread to exit!
 /// </summary>
 public static void SafeThreadCall(SendOrPostCallback d, object state)
 {
  uiContext.Send(d, state);
 }
 /// <summary>
 /// Makes a call GUI thread safe without waiting for the returned value.
 /// </summary>
 public static void SafeThreadAsyncCall(SendOrPostCallback d, object state)
 {
  uiContext.Post(d, state);
 }
}

And then I use it like:

    WorkbenchService.SafeThreadAsyncCall(delegate                                           {
    this.statusDisplay1.CallStatus = "Blah";
    this.btnCallAnswer.Text = "hello there";
}, null);
John Simons
A: 

Hello,

I found the best way to do this. And converted my code to this.

Hope this helps someone else.

 // Delegate for marshalling the call on the correct thread.
    private delegate void SetIdleStateDelegate(string callStatusMsg);

    // Set object back to idle state.
    public void SetIdleState(string callStatusMsg)
    {
        if (this.InvokeRequired)
        {
            this.Invoke(new SetIdleStateDelegate(SetIdleState), callStatusMsg);
        }
        else
        {
            this.btnCallAnswer.Text = CATWinSIP_MsgStrings.Call;
            this.btnEndCallReject.Text = CATWinSIP_MsgStrings.EndCall;
            this.btnHoldUnhold.Text = CATWinSIP_MsgStrings.Hold;

            this.btnCallAnswer.Enabled = true;
            this.btnRedial.Enabled = true;
            this.btnEndCallReject.Enabled = false;
            this.btnHoldUnhold.Enabled = false;
        }           
    }
robUK