C# 如何在asp.net中等待所有AsyncCallback返回

C# 如何在asp.net中等待所有AsyncCallback返回,c#,asp.net,asynccallback,C#,Asp.net,Asynccallback,我使用多线程数据库查询一次检索多个数据表。我使用了一个被锁定的列表…一旦所有回调都返回,我想返回列表。 我想知道如何等待所有回调完成 private Object TableLock = new Object(); private List<DataTable> tables_from_callback = new List<DataTable>(); private void ExecReaderHandleCallback(IAsyncResult result)

我使用多线程数据库查询一次检索多个数据表。我使用了一个被锁定的列表…一旦所有回调都返回,我想返回列表。 我想知道如何等待所有回调完成

private Object TableLock = new Object();
private List<DataTable> tables_from_callback = new List<DataTable>();

private void ExecReaderHandleCallback(IAsyncResult result)
{
    SqlCommand command = (SqlCommand)result.AsyncState;
    SqlDataReader reader = command.EndExecuteReader(result);
    DataTable dt = new DataTable();
    dt.Load(reader);
    lock (TableLock)
    {
        tables_from_callback.Add(dt);
    }

}

public List<DataTable> BegExecReader(String query, int query)
{
    conn = new SqlConnection(connectionString);
    try
    {
        conn.Open();
        WaitHandle[] waitHandles = new WaitHandle[query];
        IAsyncResult[] results = new IAsyncResult[query];
        SqlCommand[] cmds = new SqlCommand[query];
        for (int i = 0; i < query; i++ )
        {
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = conn;
            cmd.CommandText = query;
            cmd.CommandType = CommandType.Text;
            cmd.CommandTimeout = queryTIMEOUT;

            AsyncCallback callback = new AsyncCallback(ExecReaderHandleCallback);
            cmd.BeginExecuteReader(callback, cmd);
            cmds[i] = cmd;
        }

        /* ????
        here I need to wait for the callbacks to finish
        HOW?
        ??????? */
        return tables_from_callback;
    }
    finally
    {
        conn.Close();
    }
}
但是现在我必须使用回调,这样我就没有等待句柄了。
任何帮助都将不胜感激。

一种简单的方法是使用两种上下文都可以访问的变量。上下文是指传递回调的调用方和回调本身

    static void Main(string[] args)
    {
        int x = 1;
        Task.Run(() =>
        {
            Thread.Sleep(5000);
            Console.WriteLine("Yay!");
            x = 0;
        });

        while (x != 0) { Thread.Yield(); }

        Console.WriteLine("Done");
        Console.ReadKey(true);
    }
我正在使用Task.Run模拟回调情况;但是,这个原则仍然适用于回调的情况……不同之处在于您将使用类级别变量或(yikes)静态变量。你也可以用信号灯之类的东西,只要信号灯没有立即发出信号……就像这样

    static void Main(string[] args)
    {
        Semaphore s = new Semaphore(1, 2);
        Task.Run(() =>
        {
            s.WaitOne();
            Thread.Sleep(5000);
            Console.WriteLine("Yay!");
            s.Release();
        });

        Thread.Sleep(100);
        s.WaitOne();

        Console.WriteLine("Done");
        Console.ReadKey(true);
    }

你可以使用互斥锁。(也可以在更大范围内使用变量;但是,这可能有点太傻了)信号量可能也会工作……因为我没有一个例子可以很容易地找到答案。嘿,各位,我的代码中的“锁”语句是C++中互斥/信号量的C等价物。问题是等待异步回调。我意识到…看我的示例,它在某种程度上模拟了您的情况。可能有更好的方法来实现这一点…我只是回答您的问题。这些方法是否适合您给定的情况可能是一个意见问题。我相信,在您的示例中,信号量可以增加的次数是query+1。
    static void Main(string[] args)
    {
        Semaphore s = new Semaphore(1, 2);
        Task.Run(() =>
        {
            s.WaitOne();
            Thread.Sleep(5000);
            Console.WriteLine("Yay!");
            s.Release();
        });

        Thread.Sleep(100);
        s.WaitOne();

        Console.WriteLine("Done");
        Console.ReadKey(true);
    }