c# - 如何在 MVVM View 模型中处理 C# WPF 线程

标签 c# .net wpf multithreading

我花了很长时间弄清楚如何处理来 self 的 ViewModel 之外的类的线程。

线程源自 Track类(class)。这是 ResponseEventHandler Track 中的代码:

public delegate void ResponseEventHandler(AbstractResponse response);
public event ResponseEventHandler OnResponseEvent;

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

if (OnResponseEvent != null)
{
    OnResponseEvent(GetResponseFromCurrentBuffer());
}

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

我的 MainWindowViewModel构造函数为 OnResponseEvent 创建事件处理程序来自 Track :

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

    _Track.OnResponseEvent +=
        new Track.ResponseEventHandler(UpdateTrackResponseWindow);
}

所以,我的想法是,每次我收到来自 OnResponseEvent 的新消息时线程,我运行 UpdateTrackResponseWindow()方法。此方法会将新消息字符串附加到 ObservableCollection<string>列出名为 TrackResponseMessage 的属性:

private void UpdateTrackResponseWindow(AbstractResponse message)
{
    TrackResponseMessage.Add(FormatMessageResponseToString(message));
}

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

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

TrackResponseMessage是我的 ViewModel 中的公共(public)属性:

public ObservableCollection<String> TrackResponseMessage
{
    get { return _trackResponseMessage; }
    set
    {
        _trackResponseMessage = value;
        RaisePropertyChanged("TrackResponseMessage");
    }
}

我是否需要编码 Thread来自 Track反对我的 ViewModel?任何示例代码将不胜感激!

最佳答案

Is there a need for me to marshall the thread comming from the Track.cs object to my viewmodel? Any example code would be very appreciated!

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

如果 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 服务工作)。

关于c# - 如何在 MVVM View 模型中处理 C# WPF 线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6538633/

相关文章:

c# - 获取以下实体之间的差异 Linq to Entities

c# - 如何在 C# 中获取列表中新添加项的索引?

.net - 获取 "Cannot implicitly convert type ' 表 [ ]' to ' Generic.List<>'

c# - 查询返回匿名类型列表,需要值列表

c# - XAML 中带有黑色边框的白色字体

WPF 控件作为资源字典中的静态资源,用于多个 WPF 窗口?

c# 使用LiNQ删除Datatable中的多行

c# - 返回字符串时的编译器优化

.net - 与 HTTPModule 等效的 WCF 是什么?

wpf - Silverlight 3.0 out of browser vs WPF/Windows App - 差异总结?