我有一个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
异步运行?
答案 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