C# 如何使任务更加独立?
最初我使用线程和线程池编写C#程序,但这里的大多数用户都告诉我,异步是提高效率的更好方法。我的程序将JSON对象发送到服务器,直到返回状态代码200,然后继续执行下一个任务 问题是,一旦我的一个任务检索到状态代码为200,它将等待其他任务获取200代码,然后进入下一个任务。我希望每个任务都能继续它的下一个任务,而不必等待其他任务通过收到200个响应来完成(或赶上) 下面是我并行运行任务的主要类C# 如何使任务更加独立?,c#,.net,multithreading,asynchronous,task,C#,.net,Multithreading,Asynchronous,Task,最初我使用线程和线程池编写C#程序,但这里的大多数用户都告诉我,异步是提高效率的更好方法。我的程序将JSON对象发送到服务器,直到返回状态代码200,然后继续执行下一个任务 问题是,一旦我的一个任务检索到状态代码为200,它将等待其他任务获取200代码,然后进入下一个任务。我希望每个任务都能继续它的下一个任务,而不必等待其他任务通过收到200个响应来完成(或赶上) 下面是我并行运行任务的主要类 public static void Main (string[] args) {
public static void Main (string[] args)
{
var tasks = new List<Task> ();
for (int i = 0; i < 10; i++) {
tasks.Add (getItemAsync (i));
}
Task.WhenAny (tasks);
}
下面是检索密钥的函数,它使用HttpClient并进行解析
public static async Task getProductKey (int i)
{
string url = "http://www.website.com/key";
var stream = await client.GetStringAsync (url).ConfigureAwait(false);
var doc = new HtmlDocument ();
doc.LoadHtml (stream);
HtmlNode node = doc.DocumentNode.SelectNodes ("//input[@name='key']") [0];
try {
key = node.Attributes ["value"].Value;
} catch (Exception e) {
Console.WriteLine ("Exception: " + e);
}
}
在每个任务收到一个密钥并具有200个状态代码后,它将运行doMoreAsync()。我希望检索到200代码的任何单个任务都能运行doMoreAsync(),而不必等待其他任务的跟进。我该怎么办 您的主方法不是等待任务完成,它只是触发一系列异步任务并返回。 如果您想等待异步任务,则只能通过异步方法来完成。解决方法是从Main方法启动异步任务,并使用阻塞
task.wait()
:
您的主要问题似乎是在所有并发运行的异步操作中共享
键
字段。这将不可避免地导致种族危险。相反,您应该更改getProductKey
方法,将每个检索到的键作为其异步操作的结果返回:
// ↓ result type of asynchronous operation
public static async Task<string> getProductKey(int i)
{
// retrieval logic here
// return key as result of asynchronous operation
return node.Attributes["value"].Value;
}
最后,在主逻辑中,使用WaitAll
防止控制台应用程序在所有任务完成之前终止。虽然WaitAll
是一个阻塞调用,但在这种情况下是可以接受的,因为您希望主线程阻塞
public static void Main (string[] args)
{
var tasks = new List<Task> ();
for (int i = 0; i < 10; i++) {
tasks.Add(getItemAsync(i));
}
Task.WaitAll(tasks.ToArray());
}
publicstaticvoidmain(字符串[]args)
{
var tasks=newlist();
对于(int i=0;i<10;i++){
添加(getItemAsync(i));
}
Task.WaitAll(tasks.ToArray());
}
感谢您的回复,几分钟前我发现了ContinueWith,现在我正在测试该方法。它不断返回相同的线程。var finishedTask=wait tasks.WhenAny()不起作用。它说“System.Collections.Generic.list”不包含“whenany”的定义。我的意思是wait Task.whenany(tasks)代码>这将等待列表中的一项任务完成。然后,您可以从该列表中删除该任务,因为它已完成。此外,任务未映射到线程1:1。一组任务可以在同一个线程中执行。一个任务可以执行,而另一个任务却在等待。是的,它在我的主程序中不起作用。它给了我system.collections.generic.list错误。是的,我尝试了WaitAll()方法,但它一直给我这个wierd错误,它说,“参数#1无法转换'system.collections.generic.list'表达式到类型'system.threading.task.tasks[]”@CO:我在tasks
列表上缺少一个.ToArray()
调用。试试最新版本。是的,我不久前就知道了。它仍然不能独立工作,但该计划不会很快结束。它仍在等待所有任务检索这些键,以继续下一步。我将尝试使用ContinueWith()来实现这一点,因为某些原因,这有点棘手。在文件中似乎是直截了当的。
getItemAsync(i).ContinueWith(anotherTask);
// ↓ result type of asynchronous operation
public static async Task<string> getProductKey(int i)
{
// retrieval logic here
// return key as result of asynchronous operation
return node.Attributes["value"].Value;
}
public static async Task getItemAsync(int i)
{
string key;
try
{
key = await getProductKey(i).ConfigureAwait(false);
}
catch
{
// handle exceptions
}
// use local variable 'key' in further asynchronous operations
}
public static void Main (string[] args)
{
var tasks = new List<Task> ();
for (int i = 0; i < 10; i++) {
tasks.Add(getItemAsync(i));
}
Task.WaitAll(tasks.ToArray());
}