如何在MVVM视图模型中处理c#WPF线程

EnL*_*cha 5 .net c# wpf multithreading

我有一段时间搞清楚如何处理来自ViewModel之外的类的Thread.

Thread来自一个Track类.这是以下ResponseEventHandler代码Track:

public delegate void ResponseEventHandler(AbstractResponse response);
public event ResponseEventHandler OnResponseEvent;
Run Code Online (Sandbox Code Playgroud)

当从我的Track对象中处理"命令"方法时,以下代码运行OnResponseEvent,它将线程中的消息发送回我的ViewModel:

if (OnResponseEvent != null)
{
    OnResponseEvent(GetResponseFromCurrentBuffer());
}
Run Code Online (Sandbox Code Playgroud)

GetResponseFromCurrentBuffer()只返回一个消息类型,它是一个预定义的类型Track.

我的MainWindowViewModel构造函数创建了一个事件处理程序OnResponseEventTrack:

public MainWindowViewModel()
{
    Track _Track = new Track();

    _Track.OnResponseEvent +=
        new Track.ResponseEventHandler(UpdateTrackResponseWindow);
}
Run Code Online (Sandbox Code Playgroud)

所以,我的想法是每次有来自OnResponseEventThread的新消息时,我都会运行该UpdateTrackResponseWindow()方法.此方法将新的消息字符串附加到ObservableCollection<string>名为的列表属性TrackResponseMessage:

private void UpdateTrackResponseWindow(AbstractResponse message)
{
    TrackResponseMessage.Add(FormatMessageResponseToString(message));
}
Run Code Online (Sandbox Code Playgroud)

FormatMessageResponseToString()方法仅将消息与其中的所有预定义消息类型进行比较Track,并进行一些漂亮的字符串格式化.

主要问题是: 运行时UI消失TrackResponseMessage.Add().可执行文件仍在后台运行,结束任务的唯一方法是关闭Visual Studio 2010.

TrackResponseMessage 是我的ViewModel中的公共属性:

public ObservableCollection<String> TrackResponseMessage
{
    get { return _trackResponseMessage; }
    set
    {
        _trackResponseMessage = value;
        RaisePropertyChanged("TrackResponseMessage");
    }
}
Run Code Online (Sandbox Code Playgroud)

是否需要我将Thread来自Track对象的内容编组到我的ViewModel中?任何示例代码将非常感谢!

Ree*_*sey 10

我是否需要编组从Track.cs对象到我的viewmodel的线程?任何示例代码将非常感谢!

是.不幸的是,虽然INotifyPropertyChanged将处理来自其他线程的事件,INotifyCollectionChanged但不会(即:) ObservableCollection<T>.因此,您需要编组回VM.

如果从View(View-First MVVM)创建VM或者已知在UI线程上创建VM,则使用.NET 4任务有一个很好的选择:

TaskScheduler uiScheduler;
public MainWindowViewModel() 
{
    uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
    Track _Track = new Track();
    _Track.OnResponseEvent += new Track.ResponseEventHandler(UpdateTrackResponseWindow);
}
Run Code Online (Sandbox Code Playgroud)

然后,您的事件处理程序可以执行以下操作:

private void UpdateTrackResponseWindow(AbstractResponse message) 
{
    Task.Factory.StartNew(
       () => TrackResponseMessage.Add(FormatMessageResponseToString(message)),
       CancellationToken.None, TaskCreationOptions.None,
       uiScheduler); 
}
Run Code Online (Sandbox Code Playgroud)

这样做的好处是不会将WPF或Silverlight特定的资源和类型提取到ViewModel类中(即:)Dispatcher,同时仍然提供所有好处.它在具有线程亲和性的其他例程中也可以不变地工作(即:WCF服务工作).