异步更新来自另一个线程的wpf UI

时间:2015-09-26 12:37:50

标签: c# wpf multithreading asynchronous

我有一个WPF UI,我想通过调用一些事件从另一个线程异步更新它。

我知道如何在UI线程中调用事件并调用它们,但我想将它做为异步。

public partial class HomeUI 
{
    public HomeUI()
    {
        var test = new LogicClass();
        test.UI_StartPlaying += StartPlaying;

        new Thread(test.Start).Start();
    }

    private void StartPlaying(object sender, EventArgs e)
    {
        Dispatcher.Invoke(new Action(() =>
        {
            var streamAddress = (e as UIUpdateEventArgs).StreamAddress;
            vlc.Stop();
            vlc.Media = new LocationMedia(streamAddress);
            vlc.Play();
        }));
    }

}


public class LogicClass
{
    public event EventHandler UI_StartPlaying;
    public void Start()
    {
        DoSomethings();
        UI_StartPlaying(this, new UIUpdateEventArgs(streamAddress));
        DoSomethingElse();
    }
}

class UIUpdateEventArgs : EventArgs
{
    string StreamAddress {get; set;}
    public UIUpdateEventArgs( string streamAddress)
    {
        this.StreamNumber = streamNumber;
    }
}

但是在这段代码中,当DoSomethingElse()部分发生导致延迟或停止逻辑线程的事情时,UI会冻结。
编辑: DoSomethingElse()部分中,我运行2个线程,其中一个执行所有数据库事务并有一些延迟。这个延迟,让用户界面上的vlc暂停(冻结一个随机帧),然后冻结整个用户界面 显然,当我评论这些交易时,程序正常工作 我该怎么做才能使UIEventUpdate与我的Logic Thread异步运行?

2 个答案:

答案 0 :(得分:2)

您可以使用Dispatcher.BeginInvoke来获取所需内容。此函数直接返回,委托进行调度并稍后调用。

如果您的要求是在DoSomethingElse()完成后调用StartPlaying,则必须await Dispatcher.BeginInvoke来电。

我不知道LocationMedia但如果new LocationMedia(streamAddress);是一项昂贵的创作(需要很长时间和/或需要大量内存),我会尽可能在Dispatcher代表之外进行

var streamAddress = (e as UIUpdateEventArgs).StreamAddress;
var media = new LocationMedia(streamAddress);
Dispatcher.BeginInvoke(new Action(() =>
{
    vlc.Stop();
    vlc.Media = media;
    vlc.Play();
}));

问候!

答案 1 :(得分:1)

使用Dispatcher.InvokeAsync方法而不是Invoke方法。 MSDN Link