I'm learning about async/await with C# 4.5 and wondering what happens when multiple "awaiters" are awaiting the same task.
I'm doing some experimentation and I think that I understand what's happening. However, i have some questions to ask:
Look at this piece of code:
AsyncAwaitExperiment.fxml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace View
{
/// <summary>
/// Interaction logic for AsyncAwaitExperiment.xaml
/// </summary>
public partial class AsyncAwaitExperiment : Window
{
private CancellationTokenSource token;
private Task longRunningTask;
public AsyncAwaitExperiment()
{
InitializeComponent();
}
private void startAsyncOperation(object sender, RoutedEventArgs e)
{
if (longRunningTask != null && !longRunningTask.IsCompleted)
{
return;
}
else
{
longRunningTask = null;
token = new CancellationTokenSource();
}
Action action = () =>
{
while (!token.Token.IsCancellationRequested)
{
Thread.Sleep(100);
}
};
longRunningTask = Task.Factory.StartNew(
action,
token.Token,
TaskCreationOptions.LongRunning,
TaskScheduler.Current);
}
private void stopOperation(object sender, RoutedEventArgs e)
{
if (longRunningTask == null
|| longRunningTask.IsCompleted
|| token == null
|| token.Token.IsCancellationRequested)
{
return;
}
token.Cancel();
}
private async void firstAwait(object sender, RoutedEventArgs e)
{
if (longRunningTask == null || longRunningTask.IsCompleted)
return;
await longRunningTask;
Console.WriteLine("First Method");
}
private async void secondAwait(object sender, RoutedEventArgs e)
{
if (longRunningTask == null || longRunningTask.IsCompleted)
return;
await longRunningTask;
Console.WriteLine("Second Method");
}
}
}
AsyncAwaitExperiment.fxml
<Window x:Class="View.AsyncAwaitExperiment"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="AsyncAwaitExperiment" Height="300" Width="300">
<Grid>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<Button Content="Start Async" Margin="3" Click="startAsyncOperation" />
<Button Content="Stop Async" Margin="3" Click="stopOperation" />
<Button Content="Await First" Margin="3" Click="firstAwait" />
<Button Content="Await Second" Margin="3" Click="secondAwait" />
</StackPanel>
</Grid>
</Window>
The behavior of this code is:
With this piece of code and some break points I have noticed some behaviors.
The questions are:
PS: Sorry for my bad english :/
You shouldn't assume anything about the order in which activities will resume. Supposing that, in the future, someone managed to write a new UI system that was entirely multi-threaded, you'd expect even UI threads to run in parallel (Notes: No-one thinks it's sane to write a multi-threaded UI system currently; Even if two tasks resume "at the same time", one of them could be indefinitely paused)
If there are dependencies between activities in your code, make them explicit. Otherwise, assume that they may occur in any order and may be interleaved. That's the only sane way to program.
And, finally, no. Once you've used a CancellationToken
, it's done. If you need another one, you need to create a new one. This actually makes thinking about multiple tasks/activities simpler to think about - no token can go from being cancelled to being uncancelled.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.