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



我很难弄清楚如何处理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线程。

相关内容

  • 没有找到相关文章

最新更新