List.clear&的问题从不同步的代码块调用对象同步方法

时间:2014-08-14 10:50:48

标签: c# multithreading exception

我很难找出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"
}

我怎么能解决这个问题,我对线程很新。谢谢你的帮助。

1 个答案:

答案 0 :(得分:0)

该列表似乎与视图绑定。因此,在这种情况下,从另一个线程清除列表是非法的跨线程调用。您必须设置正确的同步上下文或实现列表的异步版本。以下是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);
  }
}