C# 如何使任务更加独立?

C# 如何使任务更加独立?,c#,.net,multithreading,asynchronous,task,C#,.net,Multithreading,Asynchronous,Task,最初我使用线程和线程池编写C#程序,但这里的大多数用户都告诉我,异步是提高效率的更好方法。我的程序将JSON对象发送到服务器,直到返回状态代码200,然后继续执行下一个任务 问题是,一旦我的一个任务检索到状态代码为200,它将等待其他任务获取200代码,然后进入下一个任务。我希望每个任务都能继续它的下一个任务,而不必等待其他任务通过收到200个响应来完成(或赶上) 下面是我并行运行任务的主要类 public static void Main (string[] args) {

最初我使用线程和线程池编写C#程序,但这里的大多数用户都告诉我,异步是提高效率的更好方法。我的程序将JSON对象发送到服务器,直到返回状态代码200,然后继续执行下一个任务

问题是,一旦我的一个任务检索到状态代码为200,它将等待其他任务获取200代码,然后进入下一个任务。我希望每个任务都能继续它的下一个任务,而不必等待其他任务通过收到200个响应来完成(或赶上)

下面是我并行运行任务的主要类

    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());
}