Ala*_*yne 6 c# wpf multithreading cancellationtokensource
这与我的其他问题如何取消后台打印有关.
我试图更好地理解CancellationTokenSource模型以及如何跨线程边界使用它.
我有一个主窗口(在UI线程上)后面的代码:
public MainWindow()
{
InitializeComponent();
Loaded += (s, e) => {
DataContext = new MainWindowViewModel();
Closing += ((MainWindowViewModel)DataContext).MainWindow_Closing;
};
}
Run Code Online (Sandbox Code Playgroud)
它在关闭时正确调用CloseWindow代码:
private void CloseWindow(IClosable window)
{
if (window != null)
{
windowClosingCTS.Cancel();
window.Close();
}
}
Run Code Online (Sandbox Code Playgroud)
通过选择菜单项,在后台线程上创建第二个窗口:
// 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();
}
}
Run Code Online (Sandbox Code Playgroud)
在MainWindowViewModel(在UI线程上),我把:
public CancellationTokenSource windowClosingCTS { get; set; }
Run Code Online (Sandbox Code Playgroud)
其构造函数为:
// Constructor
public MainMenu()
{
readers = new List<Reader>();
CloseWindowCommand = new RelayCommand<IClosable>(this.CloseWindow);
windowClosingCTS = new CancellationTokenSource();
}
Run Code Online (Sandbox Code Playgroud)
现在我的问题.当关闭UI线程上的MainWindow时,windowClosingCTS.Cancel()会立即调用使用ct注册的委托,即调用previewWindow.Close(). 这现在立即返回到"If(Windows!= null):
"调用线程无法访问此对象,因为另一个线程拥有它."
那么我做错了什么?
您的问题是您的预览窗口在另一个线程上运行。当您触发取消时,您将在该线程上执行取消标记的注册操作,而不是在运行预览的线程上执行。
这些情况下的黄金标准是不使用两个 UI 线程。这通常会引起麻烦,并且处理它们所需的工作通常是不值得的。
如果您想继续使用您的解决方案,或者如果您想从后台线程触发取消,则必须将关闭操作编组到打开窗口的线程:
Action closeAction = () => previewWindow.Close();
previewWindow.Dispatcher.Invoke(closeAction);
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
704 次 |
| 最近记录: |