我很难弄清楚如何处理ViewModel之外的类中的线程。
线程源自一个Track
类。以下是Track
:中的ResponseEventHandler
代码
public delegate void ResponseEventHandler(AbstractResponse response);
public event ResponseEventHandler OnResponseEvent;
当从我的Track
对象中处理"命令"方法时,以下代码运行OnResponseEvent
,它在线程中向我的ViewModel发送一条消息:
if (OnResponseEvent != null)
{
OnResponseEvent(GetResponseFromCurrentBuffer());
}
CCD_ 6仅返回消息类型,该消息类型是CCD_。
我的MainWindowViewModel
构造函数从Track
:为OnResponseEvent
创建一个事件处理程序
public MainWindowViewModel()
{
Track _Track = new Track();
_Track.OnResponseEvent +=
new Track.ResponseEventHandler(UpdateTrackResponseWindow);
}
因此,我们的想法是,每次我收到来自OnResponseEvent
线程的新消息时,我都会运行UpdateTrackResponseWindow()
方法。此方法将向名为TrackResponseMessage
:的ObservableCollection<string>
列表属性附加一个新消息字符串
private void UpdateTrackResponseWindow(AbstractResponse message)
{
TrackResponseMessage.Add(FormatMessageResponseToString(message));
}
FormatMessageResponseToString()
方法只是将消息与Track
中所有预定义的消息类型进行比较,并进行一些巧妙的字符串格式化。
主要问题是:运行TrackResponseMessage.Add()
时UI消失。可执行文件仍在后台运行,结束任务的唯一方法是关闭Visual Studio 2010。
TrackResponseMessage
是我的ViewModel:中的公共属性
public ObservableCollection<String> TrackResponseMessage
{
get { return _trackResponseMessage; }
set
{
_trackResponseMessage = value;
RaisePropertyChanged("TrackResponseMessage");
}
}
是否需要将来自Track
对象的Thread
封送到我的ViewModel?任何示例代码都将不胜感激!
我是否需要将Track.cs对象中的线程组合整理到我的视图模型中?任何示例代码都将不胜感激!
是的。不幸的是,虽然INotifyPropertyChanged
将处理来自其他线程的事件,但INotifyCollectionChanged
不处理(即:ObservableCollection<T>
)。因此,您需要封送回VM。
如果虚拟机是从View(View First MVVM)创建的,或者已知是在UI线程上创建的,那么使用.NET 4任务有一个很好的选择:
TaskScheduler uiScheduler;
public MainWindowViewModel()
{
uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
Track _Track = new Track();
_Track.OnResponseEvent += new Track.ResponseEventHandler(UpdateTrackResponseWindow);
}
然后,稍后,您的事件处理程序可以执行以下操作:
private void UpdateTrackResponseWindow(AbstractResponse message)
{
Task.Factory.StartNew(
() => TrackResponseMessage.Add(FormatMessageResponseToString(message)),
CancellationToken.None, TaskCreationOptions.None,
uiScheduler);
}
这有一个很好的优点,即不将WPF或Silverlight特定的资源和类型拉入ViewModel类(即:Dispatcher
),同时仍然提供所有好处。它还可以在其他具有线程亲和性的例程(即WCF服务工作)中工作,但没有改变。
如果RaisePropertychanged是在UI线程以外的线程上执行的,并且该事件的事件处理程序接触到了UI,则需要切换到UI线程。