This is related to my other question How to cancel background printing .
I am trying to better understand the CancellationTokenSource model and how to use it across thread boundaries.
I have a main window (in the user interface thread) where the code is located:
public MainWindow() { InitializeComponent(); Loaded += (s, e) => { DataContext = new MainWindowViewModel(); Closing += ((MainWindowViewModel)DataContext).MainWindow_Closing; }; }
which correctly calls CloseWindow code when it is closed:
private void CloseWindow(IClosable window) { if (window != null) { windowClosingCTS.Cancel(); window.Close(); } }
When you select a menu item in the background stream, a second window is created:
// 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(); } }
In MainWindowViewModel (in the UI thread) I put:
public CancellationTokenSource windowClosingCTS { get; set; }
With its constructor:
// Constructor public MainMenu() { readers = new List<Reader>(); CloseWindowCommand = new RelayCommand<IClosable>(this.CloseWindow); windowClosingCTS = new CancellationTokenSource(); }
Now my problem. When MainWindow is closed in the user interface thread, windowClosingCTS.Cancel () calls an immediate delegate registered with ct, i.e. Called previewWindow.Close (). Now it immediately returns to the If (Windows! = Null) section with:
"The calling thread cannot access this object because another thread owns it."
So what am I doing wrong?