Tôi đã một DLL mà chạy một sợi nhân viên và gửi các sự kiện trở lại ứng dụng - làm việc một cách hoàn hảo trên cửa sổ hình thức, chuyển sang WPF và tất cả mọi thứ ngừng làm việc. Tôi đã đập đầu của tôi vào một bức tường gạch trong 4 giờ cố gắng để có được điều này để làm việc. Nhưng giải pháp mà tôi đã kết thúc, nhờ vào UI Thread Safe của SafeCarshectionSynchronization của Microsoft, cung cấp một triển khai thực sự rõ ràng để giải quyết vấn đề này.
Bộ sưu tập này mở rộng ObservableCollection và triển khai EnableCollectionSynchronization làm cho các đối tượng này có thể sử dụng được giữa WPF và nhân viên nền.
Sửa: Microsoft's docs nói sau đây, vì vậy tôi sẽ cho rằng việc chia sẻ nội dung đối tượng không quan trọng.
Tham số ngữ cảnh là một đối tượng tùy ý mà bạn có thể sử dụng để biết thông tin khi bạn bật đồng bộ hóa bộ sưu tập. Bối cảnh có thể là null.
ThreadSafeCollection.cs
using System.Collections.ObjectModel;
using System.Windows.Data;
namespace NSYourApplication
{
/// <summary>
/// This ObservableCollection is thread safe
/// You can update it from any thread and the changes will be safely
/// marshalled to the UI Thread WPF bindings
/// Thanks Microsoft!
/// </summary>
/// <typeparam name="T">Whatever type of collection you want!</typeparam>
public class ThreadSafeCollection<T> : ObservableCollection<T>
{
private static object __threadsafelock = new object();
public ThreadSafeCollection()
{
BindingOperations.EnableCollectionSynchronization(this, __threadsafelock);
}
}
}
Ví dụ WindowViewModel WindowViewModel.cs
namespace NSYourApplication
{
/// <summary>
/// Example View
/// BaseModelView implements "PropertyChanged" to update WPF automagically
/// </summary>
class TestViewModel : BaseModelView
{
public ThreadSafeCollection<string> StringCollection { get; set; }
/// <summary>
/// background thread implemented elsewhere...
/// but it calls this method eventually ;)
/// Depending on the complexity you might want to implement
/// [MethodImpl(MethodImplOptions.Synchronized)]
/// to Synchronize multiple threads to prevent chase-conditions,deadlocks etc
/// </summary>
public void NonUIThreadMethod()
{
// No dispatchers or invokes required here!
StringCollection.Add("Some Text from a background worker");
}
/// <summary>
/// Somewhere in the UIThread code it'll call this method
/// </summary>
public void UIThreadMethod()
{
StringCollection.Add("This text come from UI Thread");
}
/// <summary>
/// Constructor, creates a thread-safe collection
/// </summary>
public TestViewModel()
{
StringCollection = new ThreadSafeCollection<string>();
}
}
}
Cách sử dụng trong một ListBox trong một XAML cửa sổ/kiểm soát MainWindow.xaml
<ListBox x:Name="wpfStringCollection" ItemsSource="{Binding StringCollection,Mode=OneWay}">
</ListBox>
Nguồn
2017-08-21 23:21:11
Vì vậy, bằng cách thêm chúng vào bộ sưu tập các mục trong chuỗi nền sẽ cập nhật các điều khiển trên chuỗi giao diện người dùng? Nó hoạt động như thế nào? – Mark
Không, bạn thêm chúng vào chủ đề bộ điều phối, nhưng với ưu tiên thấp hơn và trong chucnks nhỏ hơn để giao diện người dùng vẫn đáp ứng – Bubblewrap
Tôi thấy, cảm ơn tôi sẽ thử một lần – Mark