I am little confuced by the followed situation. If I call SleepBeforeInvoke
method, application is suspended on the _task.Wait();
string. But if I call SleepAfterInvoke
method, application works fine and control will reach catch
clause. Calling the BeginInvoke
method works fine as well.
Could anyone explain with maximum details what's the difference between these three methods usage? Why application is suspended if I use SleepBeforeInvoke
method, and why it is not if I use SleepAfterInvoke
and BeginInvoke
methods? Thanks.
Win 7, .Net 4.0
xaml:
<Grid>
<Grid.RowDefinitions>
<RowDefinition></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0"
Name="_textBlock"
Text="MainWindow"></TextBlock>
<Button Grid.Row="1"
Click="ButtonBase_OnClick"></Button>
</Grid>
.cs:
public partial class MainWindow : Window
{
private readonly CancellationTokenSource _cts = new CancellationTokenSource();
private Task _task;
/// <summary>
/// Application wiil be suspended on string _task.Wait();
/// </summary>
private void SleepBeforeInvoke()
{
for (Int32 count = 0; count < 50; count++)
{
if (_cts.Token.IsCancellationRequested)
_cts.Token.ThrowIfCancellationRequested();
Thread.Sleep(500);
Application.Current.Dispatcher.Invoke(new Action(() => { }));
}
}
/// <summary>
/// Works fine, control will reach the catch
/// </summary>
private void SleepAfterInvoke()
{
for (Int32 count = 0; count < 50; count++)
{
if (_cts.Token.IsCancellationRequested)
_cts.Token.ThrowIfCancellationRequested();
Application.Current.Dispatcher.Invoke(new Action(() => { }));
Thread.Sleep(500);
}
}
/// <summary>
/// Works fine, control will reach the catch
/// </summary>
private void BeginInvoke()
{
for (Int32 count = 0; count < 50; count++)
{
if (_cts.Token.IsCancellationRequested)
_cts.Token.ThrowIfCancellationRequested();
Thread.Sleep(500);
Application.Current.Dispatcher.BeginInvoke(new Action(() => { }));
}
}
public MainWindow()
{
InitializeComponent();
_task = Task.Factory.StartNew(SleepBeforeInvoke, _cts.Token, TaskCreationOptions.None, TaskScheduler.Default);
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
try
{
_cts.Cancel();
_task.Wait();
}
catch (AggregateException)
{
}
Debug.WriteLine("Task has been cancelled");
}
}