7.12.2016

Update UI from thread

來自:Update your form from another thread
public static TResult SafeInvoke<t,>(this T isi, Func<t,> call) where T : ISynchronizeInvoke
{
    if (isi.InvokeRequired) 
    { 
        IAsyncResult result = isi.BeginInvoke(call, new object[] { isi }); 
        object endResult = isi.EndInvoke(result); return (TResult)endResult; 
    }
    else
        return call(isi);
}

public static void SafeInvoke<t>(this T isi, Action<t> call) where T : ISynchronizeInvoke
{
    if (isi.InvokeRequired) 
        isi.BeginInvoke(call, new object[] { isi });
    else
        call(isi);
}

Usage:

lblProcent.SafeInvoke(d => d.Text = "Written by the background thread");
progressBar1.SafeInvoke(d => d.Value = i);

//or call a methode thread safe. That method is executed on the same thread as the form
this.SafeInvoke(d => d.UpdateFormItems("test1", "test2"));


// A threadSafe getter is also available. The getter knows what the return type is, so casting is not necessary.
string textboxtext=textbox.SafeInvoke(d=>d.textbox.text);

Another way, like Event broke
Synchronizing calls to the UI in a multi threaded application
public class MessageBroker
{
    private readonly Dictionary<Type, object> consumers;
    private readonly SynchronizationContext synchronizationContext;

    public MessageBroker()
    {
        consumers = new Dictionary<Type, object>();
        synchronizationContext = AsyncOperationManager.SynchronizationContext;
    }

    public void Send<T>(T message)
    {
        var key = typeof(T);
        if (!consumers.ContainsKey(key)) return;

        var list = consumers[key] as List<Action<T>>;
        list.ForEach(action =>
            synchronizationContext.Post(m => action((T)m), message));
    }

    public void Register<T>(Action<T> action)
    {
        var key = typeof (T);
        List<Action<T>> list;
        if (!consumers.ContainsKey(key))
        {
            list = new List<Action<T>>();
            consumers.Add(key, list);
        }
        else
            list = consumers[key] as List<Action<T>>;
        list.Add(action);
    }
}
Message Bus
public static class MessageBus
{
    private static MessageBroker messageBroker;

    private static MessageBroker Broker
    {
        get
        {
            if (messageBroker == null)
                messageBroker = new MessageBroker();
            return messageBroker;
        }
    }

    public static void Send<T>(T message)
    {
        Broker.Send(message);
    }

    public static void Register<T>(Action<T> action)
    {
        Broker.Register(action);
    }
}
最後一種方式跟以上的方向剛好相反,在UI上用個Timer,定時取得來源資料,並更新到表單上,就不用考慮執行緒更新的問題了…
Written with StackEdit.