как дождаться, пока все AsyncCallback вернутся в asp.net

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

Я сделал что-то подобное, не используя обратные вызовы, где

 IAsyncResult result = cmd.BeginExecuteReader();
results[i] = resu<
waitHandles[i] = result.AsyncWaitHandle;
...
WaitHandle.WaitAll(waitHandles);
 

но теперь Я ДОЛЖЕН использовать обратный вызов, чтобы у меня не было дескрипторов ожидания.
Любая помощь будет оценена.

Комментарии:

1. Вероятно, вы могли бы использовать мьютекс. (Вы также можете использовать переменную в более глобальной области; однако, это, вероятно, немного глупо.)

2. Семафор, вероятно, тоже будет работать … не опубликовал в качестве ответа, потому что у меня нет готового примера.

3. привет, ребята, этот оператор ‘lock’ в моем коде является эквивалентом c # мьютекса / семафора в c . Проблема заключается в ожидании асинхронных обратных вызовов.

4. Я понимаю, что … смотрите Мой пример, который несколько имитирует вашу ситуацию.

5. возможно, есть лучший способ сделать это… Я просто отвечаю на ваш вопрос. Являются ли методы подходящими для вашей конкретной ситуации, вероятно, вопрос мнения.

Ответ №1:

Простой способ сделать это — использовать переменную, к которой имеют доступ оба контекста. Под контекстом я подразумеваю вызывающего абонента, который передает обратный вызов, и сам обратный вызов.

     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.Запустите, чтобы смоделировать ситуацию обратного вызова; однако принцип по-прежнему применяется в случае обратного вызова…разница в том, что вы бы использовали переменную уровня класса или (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);
    }
 

Комментарии:

1. Я полагаю, что в вашем примере количество раз, когда семафор может быть увеличен, равно query 1.