【问题标题】:Threadlocking on the ViewModel in WPFWPF 中 ViewModel 上的线程锁定
【发布时间】:2015-09-22 06:07:45
【问题描述】:

我有一个 WPF 应用程序,它使用同一类的两个对象异步调用 Web 服务。来自调用的两个事件处理程序的结果响应集合应放入作为数据绑定到 UI 的同一个字典中。 我的问题是当 web 服务返回集合并尝试插入同一个字典时出现线程锁。

public class myClass : Window
{
    public MyService serv1 {get;set;}
    public MyService serv2 {get;set;}

    public ObservableDictionary<string, MySertvice> dict = new ObservableDictionary<string, MySertvice>();

    public ObservableDictionary<string, MySertvice> Dict_VM {get;set;}


    public myClass()
    {
        InitializeComponent()
        this.DataContext = Dict;

        serv1 = new MyService("serviceA");
        serv1.CallBack += CallBack;

        serv2 = new MyService("serviceB");
        serv2.CallBack += CallBack;
    }

    public Window_Loaded(object sender, WindowloadedEventArgs e)
    {
        serv1.DoServiceCallAsync();
        Debug.WriteLine("- first call");
        serv2.DoServiceCallAsync();
        Debug.WriteLine("- second call");
    }

    public void CallBack(object sender, CallBackEventArgs e)
    {
        Debug.WriteLine("- callback");
        foreach(var name in e.ResultCollection)
        {
            dict.Add(name, sender as MyService);
        }
    }
}

输出是:

  • 第一次通话
  • 第二次通话
  • 回调
  • 回调

我的问题是,使其线程安全的最佳方法是什么?

这只是一个示例,所以逻辑无关紧要。我想要 ResultCollection 的每个元素。我的第一个想法是将结果转移到队列或并发队列中,并让后台工作人员将其从队列中处理到字典中。我真的很想要最好的方法

【问题讨论】:

  • 为什么不使用ConcurrentObservableDictionary
  • 向集合中添加项目是否必须是线程安全的..?你能描述一个有问题的场景吗?我的意思是,为什么将对象(A,B,C)与对象(D,E,F)同时添加有问题。?您是否要求第一次调用 return 必须完成添加项目,然后第二次调用才能开始添加它的项目?
  • 是的,它必须这样做。多个异步回调必须能够同时添加到对象中。这是一个包含两个服务的示例,实际上(我的真实世界场景)我有一个服务集合。它必须收集实时监控数据。处理单个服务的时间至关重要
  • 为什么不使用 Dispatcher 将更新编组到 UI 线程上? Dispatcher 是线程安全的,可以很好地管理多个调用。您只能通过生成一个线程来为您提供结果的 ConcurrentQueue 提供服务来模拟它。
  • 你能给我一个例子或链接吗?

标签: c# wpf asynchronous mvvm


【解决方案1】:

给你。如果您对并发收集没有信心,那么:

private Object thisLock = new Object();

public void CallBack(object sender, CallBackEventArgs e)
{
    Debug.WriteLine("- callback");
    lock(thisLock )
    {            
        foreach(var name in e.ResultCollection)
        {
            dict.Add(name, sender as MyService);
        }
    }
}

希望对您有所帮助。

【讨论】:

  • 这是否会锁定第​​一个的字典,而另一个会被搁置直到第一个完成?处理模式会像 AAAAABBBBB 还是更像 ABAABBBABA?
  • 这将是类似于 AAAAABBBBB 的处理模式。锁始终是线程安全的,但会降低性能。
  • 我怀疑这一点。我怎样才能实现 ABAABBBABA 模式。我猜是并发集合?
  • 我不能,因为您更改了列表。一些并发集合被列表阻止和/或项目阻止。
  • 会一一添加到 concurrentQueue (来自两者)就可以了。我想达到漏斗的效果。让多个数据注入并尽可能对其进行处理。这就是为什么我在考虑让 Backgroudworker 进行处理。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-07
  • 1970-01-01
  • 2021-01-23
  • 1970-01-01
相关资源
最近更新 更多