【发布时间】:2016-12-07 05:58:41
【问题描述】:
这与我的另一个问题How to cancel background printing 有关。
我试图更好地理解 CancellationTokenSource 模型以及如何跨线程边界使用它。
我有一个主窗口(在 UI 线程上),后面的代码在其中:
public MainWindow()
{
InitializeComponent();
Loaded += (s, e) => {
DataContext = new MainWindowViewModel();
Closing += ((MainWindowViewModel)DataContext).MainWindow_Closing;
};
}
关闭时正确调用 CloseWindow 代码:
private void CloseWindow(IClosable window)
{
if (window != null)
{
windowClosingCTS.Cancel();
window.Close();
}
}
选择菜单项后,会在后台线程上创建第二个窗口:
// Print Preview
public static void PrintPreview(FixedDocument fixeddocument, CancellationToken ct)
{
// Was cancellation already requested?
if (ct.IsCancellationRequested)
ct.ThrowIfCancellationRequested();
...............................
// Use my custom document viewer (the print button is removed).
var previewWindow = new PrintPreview(fixedDocumentSequence);
//Register the cancellation procedure with the cancellation token
ct.Register(() =>
previewWindow.Close()
);
previewWindow.ShowDialog();
}
}
在 MainWindowViewModel(在 UI 线程上),我放了:
public CancellationTokenSource windowClosingCTS { get; set; }
其构造函数为:
// Constructor
public MainMenu()
{
readers = new List<Reader>();
CloseWindowCommand = new RelayCommand<IClosable>(this.CloseWindow);
windowClosingCTS = new CancellationTokenSource();
}
现在我的问题。在 UI 线程上关闭 MainWindow 时,windowClosingCTS.Cancel() 会立即调用 ct 注册的委托,即调用 previewWindow.Close()。 现在立即返回" If (Windows != null) with:
"调用线程无法访问该对象,因为不同的 线程拥有它。”
那我做错了什么?
【问题讨论】:
-
我假设您正在使用 WPF?
-
你不应该在这个过程中使用多线程。您不受 CPU 限制。坚持使用异步单线程。
-
@d.moncada 是 MVVM。
-
@Aron 啊...你失去了我...
-
"在后台线程上创建了第二个窗口:"你为什么使用后台线程?
标签: c# wpf multithreading cancellationtokensource