Вызвать делегата для многих элементов управления - PullRequest
2 голосов
/ 13 мая 2009

C # 2008 SP1

Функция ниже будет вызываться из другого потока. Таким образом, сам элемент управления должен быть вызван, чтобы правильный поток, создавший их, мог изменить свойства.

Однако, поскольку у меня есть много элементов управления, которые необходимо обновить. Я действительно не хочу писать все эти делегаты для каждого. Я сделал один ниже. Тем не менее, я думаю, что это много кода. Есть ли способ сократить это?

Большое спасибо,

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

Ответы [ 4 ]

1 голос
/ 13 мая 2009

Я задал похожий вопрос . Ответ, который дал Джон Скит, - лучший подход, с которым я столкнулся. Соответствующий код ниже.

Создание статического вспомогательного метода:

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

В вашем примере вы можете использовать его как:

InvokeIfNecessary(statusDisplay1, delegate {statusDisplay1.CallStatus = callStatusMsg;});
1 голос
/ 13 мая 2009

Вот что я сделал в предыдущем проекте:

Я написал вспомогательный статический класс.

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

А потом я использую это как:

    WorkbenchService.SafeThreadAsyncCall(delegate                                                   {
    this.statusDisplay1.CallStatus = "Blah";
    this.btnCallAnswer.Text = "hello there";
}, null);
1 голос
/ 13 мая 2009

Как насчет чего-то вроде:

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

      {

           this.statusDisplay1.CallStatus = callStatusMsg;

          return null;

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

    }
0 голосов
/ 13 мая 2009

Я нашел лучший способ сделать это. И преобразовал мой код в это.

Надеюсь, это поможет кому-то еще.

 // 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;
        }           
    }      
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...