异步任务暂停环路简历 [英] Async Tasks Pause Resume of Loop
本文介绍了异步任务暂停环路简历的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我有一个样品code,从MSDN拍摄,我想实现while循环中的暂停/恢复功能。任何人可以提出一个解决方案/ parern这将喊得呢?
专用异步无效startButton_Click(对象发件人,RoutedEventArgs E)
{
resultsTextBox.Clear(); //实例化CancellationTokenSource。
CTS =新CancellationTokenSource(); 尝试
{
等待AccessTheWebAsync(cts.Token);
resultsTextBox.Text + =\\ r \\ nDownloads完整的。
}
赶上(OperationCanceledException)
{
resultsTextBox.Text + =\\ r \\ nDownloads取消\\ r \\ n;
}
赶上(例外)
{
resultsTextBox.Text + =\\ r \\ nDownloads失败\\ r \\ n;
} CTS = NULL;
}
私人无效cancelButton_Click(对象发件人,RoutedEventArgs E)
{
如果(CTS!= NULL)
{
cts.Cancel();
}
}
异步任务AccessTheWebAsync(CT的CancellationToken)
{
HttpClient的客户端=新的HttpClient(); //使Web地址的列表。
清单<串GT; urlList = SetUpURLList(); // ***创建查询,在执行时,返回的任务集合。
IEnumerable的<任务< INT>> downloadTasksQuery =
从urlList URL选择ProcessURL(URL,客户端,CT); // ***用了ToList执行查询并启动任务。
清单<任务< INT>> downloadTasks = downloadTasksQuery.ToList(); // ***添加一个循环来处理的任务之一在一个时间,直到没有剩余。
而(downloadTasks.Count大于0)
{
//标识完成了第一个任务。
任务< INT> firstFinishedTask =等待Task.WhenAny(downloadTasks); // ***从列表中删除所选的任务,这样你不
//过程中,它超过一次。
downloadTasks.Remove(firstFinishedTask); //等待完成的任务。
INT长度=等待firstFinishedTask;
resultsTextBox.Text + =的String.Format(下载的\\ r \\ nLength:{0},长度);
}
}
解决方案
有一个的 MSDN文章,这与使用解决了一个 PauseToken
(类似于的CancellationToken
)。
下面是从本文的示例code演示了这一概念:
命名空间PauseTokenTestApp
{
公共类PauseTokenSource
{
私人挥发性TaskCompletionSource<布尔> m_paused;
内部静态只读任务s_completedTask = Task.FromResult(真); 公共BOOL isPaused得到
{
{返回m_paused!= NULL; }
组
{
如果(值)
{
Interlocked.CompareExchange(
REF m_paused,新TaskCompletionSource<布尔>(),NULL);
}
其他
{
而(真)
{
VAR TCS = m_paused;
如果(TCS == NULL)回报;
如果(Interlocked.CompareExchange(REF m_paused,空,TCS)== TCS)
{
tcs.SetResult(真);
打破;
}
}
}
}
}
公共PauseToken令牌{{返回新PauseToken(本); }} 内部任务WaitWhilePausedAsync()
{
VAR CUR = m_paused;
返回恶狗!= NULL? cur.Task:s_completedTask;
}
} 公共结构PauseToken
{
私人只读PauseTokenSource m_source;
内部PauseToken(PauseTokenSource源){m_source =来源; } 公共BOOL isPaused得到{{返回m_source = NULL&放大器;!&安培; m_source.IsPaused; }} 公共任务WaitWhilePausedAsync()
{
返回isPaused得到?
m_source.WaitWhilePausedAsync():
PauseTokenSource.s_completedTask;
}
} 类节目
{
静态无效的主要()
{
VAR点=新PauseTokenSource();
Task.Run(()=>
{
而(真)
{
到Console.ReadLine();
!pts.IsPaused = pts.IsPaused;
}
});
SomeMethodAsync(pts.Token).Wait();
} 公共静态异步任务SomeMethodAsync(PauseToken暂停)
{
的for(int i = 0; I< 100;我++)
{
Console.WriteLine(ⅰ);
等待Task.Delay(100);
等待pause.WaitWhilePausedAsync();
}
}
}
}
I have a sample code, taken from MSDN, to which I would like implement the Pause / Resume functionality within while loop. Could anybody propose a solution / parern which would hande this?
private async void startButton_Click(object sender, RoutedEventArgs e)
{
resultsTextBox.Clear();
// Instantiate the CancellationTokenSource.
cts = new CancellationTokenSource();
try
{
await AccessTheWebAsync(cts.Token);
resultsTextBox.Text += "\r\nDownloads complete.";
}
catch (OperationCanceledException)
{
resultsTextBox.Text += "\r\nDownloads canceled.\r\n";
}
catch (Exception)
{
resultsTextBox.Text += "\r\nDownloads failed.\r\n";
}
cts = null;
}
private void cancelButton_Click(object sender, RoutedEventArgs e)
{
if (cts != null)
{
cts.Cancel();
}
}
async Task AccessTheWebAsync(CancellationToken ct)
{
HttpClient client = new HttpClient();
// Make a list of web addresses.
List<string> urlList = SetUpURLList();
// ***Create a query that, when executed, returns a collection of tasks.
IEnumerable<Task<int>> downloadTasksQuery =
from url in urlList select ProcessURL(url, client, ct);
// ***Use ToList to execute the query and start the tasks.
List<Task<int>> downloadTasks = downloadTasksQuery.ToList();
// ***Add a loop to process the tasks one at a time until none remain.
while (downloadTasks.Count > 0)
{
// Identify the first task that completes.
Task<int> firstFinishedTask = await Task.WhenAny(downloadTasks);
// ***Remove the selected task from the list so that you don't
// process it more than once.
downloadTasks.Remove(firstFinishedTask);
// Await the completed task.
int length = await firstFinishedTask;
resultsTextBox.Text += String.Format("\r\nLength of the download: {0}", length);
}
}
解决方案
There is an MSDN article that solves this using a PauseToken
(similar to a CancellationToken
).
Here's the sample code from that article that demonstrates this concept:
namespace PauseTokenTestApp
{
public class PauseTokenSource
{
private volatile TaskCompletionSource<bool> m_paused;
internal static readonly Task s_completedTask = Task.FromResult(true);
public bool IsPaused
{
get { return m_paused != null; }
set
{
if (value)
{
Interlocked.CompareExchange(
ref m_paused, new TaskCompletionSource<bool>(), null);
}
else
{
while (true)
{
var tcs = m_paused;
if (tcs == null) return;
if (Interlocked.CompareExchange(ref m_paused, null, tcs) == tcs)
{
tcs.SetResult(true);
break;
}
}
}
}
}
public PauseToken Token { get { return new PauseToken(this); } }
internal Task WaitWhilePausedAsync()
{
var cur = m_paused;
return cur != null ? cur.Task : s_completedTask;
}
}
public struct PauseToken
{
private readonly PauseTokenSource m_source;
internal PauseToken(PauseTokenSource source) { m_source = source; }
public bool IsPaused { get { return m_source != null && m_source.IsPaused; } }
public Task WaitWhilePausedAsync()
{
return IsPaused ?
m_source.WaitWhilePausedAsync() :
PauseTokenSource.s_completedTask;
}
}
class Program
{
static void Main()
{
var pts = new PauseTokenSource();
Task.Run(() =>
{
while (true)
{
Console.ReadLine();
pts.IsPaused = !pts.IsPaused;
}
});
SomeMethodAsync(pts.Token).Wait();
}
public static async Task SomeMethodAsync(PauseToken pause)
{
for (int i = 0; i < 100; i++)
{
Console.WriteLine(i);
await Task.Delay(100);
await pause.WaitWhilePausedAsync();
}
}
}
}
这篇关于异步任务暂停环路简历的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文