【问题标题】:Issue with List.clear & Object sync method was called from an unsynchronized block of code从未同步的代码块调用 List.clear 和对象同步方法的问题
【发布时间】:2014-08-14 10:50:48
【问题描述】:

我很难找出 List.Clear() 方法的问题。我的应用程序在不同的时间崩溃,例如 30 分钟到 5 小时。它发生得非常随机。

下面的代码在后台线程中启动。 我还有一些其他线程同时工作,有些线程可以使用 loggedData1 和 loggedData2 变量。

try
{
    while (true)
    {
        if (LoggingEnabled)
        {
            var stopwatch = Stopwatch.StartNew();
            #region - Reset logging variables
            loggedData2.Clear(); // List
            loggedData1.Clear(); // List
            #endregion

            // Lots of more code
        }
    }
}
catch (Exception ex)
{
    // Crashing exception given is "Object synchronization method was called from an unsyncronized block of code"
}

我该如何解决这个问题,我对 Threads 很陌生。感谢您的帮助。

【问题讨论】:

  • List<T> 不是线程安全的。考虑使用ConcurrentBag<T>
  • 你没有告诉我们问题出在哪里。我很确定你有Monitor.Exit 电话或lock 某处,发布该代码。否则很难提供帮助。
  • @YuvalItzchakov ConcurrentBag 没有 Clear()
  • @svick 然后清除任何其他并发集合。这是一个建议(可能不是最好的)

标签: c# multithreading exception


【解决方案1】:

列表似乎绑定到一个视图。所以在这种情况下,从另一个线程清除列表是非法的跨线程调用。您必须设置正确的同步上下文或实现列表的异步版本。这是 ObservableCollection 的示例

public class AsyncObservableCollection<T> : ObservableCollection<T>
{
  private readonly SynchronizationContext _synchronizationContext = SynchronizationContext.Current;

  public AsyncObservableCollection()
  {
  }

  public AsyncObservableCollection(IEnumerable<T> list) : base(list)
  {
  }

  protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
  {
    if (SynchronizationContext.Current == _synchronizationContext)
    {
      // Execute the CollectionChanged event on the current thread
      RaiseCollectionChanged(e);
    }
    else
    {
      // Post the CollectionChanged event on the creator thread
      _synchronizationContext.Post(RaiseCollectionChanged, e);
    }
  }

  private void RaiseCollectionChanged(object param)
  {
    // We are in the creator thread, call the base implementation directly
    base.OnCollectionChanged((NotifyCollectionChangedEventArgs) param);
  }

  protected override void OnPropertyChanged(PropertyChangedEventArgs e)
  {
    if (SynchronizationContext.Current == _synchronizationContext)
    {
      // Execute the PropertyChanged event on the current thread
      RaisePropertyChanged(e);
    }
    else
    {
      // Post the PropertyChanged event on the creator thread
      _synchronizationContext.Post(RaisePropertyChanged, e);
    }
  }

  private void RaisePropertyChanged(object param)
  {
    // We are in the creator thread, call the base implementation directly
    base.OnPropertyChanged((PropertyChangedEventArgs) param);
  }
}

【讨论】:

    猜你喜欢
    • 2011-11-28
    • 1970-01-01
    • 1970-01-01
    • 2015-02-06
    • 2012-09-14
    • 2013-01-05
    • 1970-01-01
    • 2012-02-19
    • 2012-12-09
    相关资源
    最近更新 更多