【发布时间】:2015-12-15 17:52:50
【问题描述】:
我正在使用 C# 4.5 学习异步/等待,并想知道当多个“等待者”等待同一任务时会发生什么。
我正在做一些实验,我认为我了解正在发生的事情。但是,我有一些问题要问:
看这段代码:
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>
这段代码的行为是:
- 按钮时启动异步长时间运行操作 按下“开始”。
- 当按钮“停止”时停止异步操作 按下。
- 当按下“第一个等待”按钮时,等待任务 完成,然后在控制台上打印一些东西。
- 与第二个按钮相同(“第二个等待”)。
通过这段代码和一些断点,我注意到了一些行为。
- 当我等待一个任务时,它会从原来的位置恢复代码 之前停过。我猜这里没有什么新鲜事。
- 如果(这是有趣的部分)我有多个“等待者” 同样的任务,它将按照等待的代码顺序恢复。 EX:如果先点击了 firstAwait,然后点击了 secondAwait, 当任务完成并且代码流的恢复将遵循 相同的顺序:先等待,然后再等待。
问题是:
- 这种行为是否有任何保证(关于 简历)?
- 使用这个调度器(TaskScheduler.Current)有什么问题吗 ?
- 我可以重复使用取消令牌还是真的需要创建一个 每次我取消并开始一项任务?
PS:抱歉我的英语不好:/
【问题讨论】:
-
我不认为它是有保证的,我不想假设它是这样,然后得到损坏的代码。如果代码片段之间存在其他依赖关系(例如您确实需要特定的顺序),为什么不明确说明呢?
-
多个等待者不是一个典型的场景——在这种人为的情况下,我不会对可能发生或可能不会发生的事情做出任何假设。此外,您使用的是
async void,这使得异步方法本质上是触发并忘记。您的应用程序可以在这些方法完成之前终止。在任何情况下,从await恢复可以发生在任何线程、任何内核上。 -
@Damien_The_Unbeliever 在这种情况下不需要特定的顺序。我怀疑的是行为,只是它。
-
主要问题是我没有找到任何关于排序的信息,编译器也没有警告过这样的事情。
-
那么,如果我们说“什么都不做”,那么您的进展如何?那肯定是起点。这个问题看起来你正在寻求特定的保证
标签: c# .net asynchronous async-await