Creo que su respuesta es una devolución de llamada.
Al configurar sus hilos de larga ejecución, pase una referencia a un método. Puede pasar el método de devolución de llamada al método de tarea, o puede configurar una instancia de delegado AsyncCallback, que está incorporada en la función BeginInvoke() de delegados.
Aquí hay un ejemplo básico:
public void StartMyTwoTasks()
{
//I'm passing the callback to the task method directly; you may prefer to pass it to BeginInvoke()
var task1Lambda =()=>Task1(TaskCompleted);
var task2Lambda =()=>Task2(TaskCompleted);
task1Lambda.BeginInvoke(null,null);
task2Lambda.BeginInvoke(null,null);
}
public void Task1(Action<int> task1Complete)
{
//perform your long-running calculation or data retrieval/transformation here
Thread.Sleep(10000);
//when finished, call the callback method.
//You may need to use Control.Invoke() to make sure the callback is executed on the UI thread
//If you use the AsyncCallback feature of BeginInvoke/EndInvoke, you don't have to make the call here.
taskComplete(1);
}
public void Task2(Action<int> taskComplete)
{
//Ditto
Thread.Sleep(8000);
taskComplete(2);
}
public void Task1Complete(int taskNumber)
{
TasksComplete[taskNumber-1] = true;
If(TasksComplete.All(x=>x==true))
DoSomethingOnceAllTasksAreComplete();
}
Uso de la función AsyncCallback, el método de devolución de llamada tiene que ajustarse a una definición delegado particular que acepta el IAsyncResult, pero usted no tiene que preocuparse de que la invoca correctamente tu método; el marco maneja la devolución de llamada para usted:
public public void StartALongTask()
{
var taskLambda =()=>PerformTask();
taskLambda.BeginInvoke(TaskComplete,null);
}
//one advantage is that you can call a method that returns a value very easily.
public IEnumerable<string> PerformTask()
{
//long-running task
Thread.Sleep(5000);
return Enumerable.Repeat("result", 100);
//look ma, no callback invocation.
//This makes asynchronous delegates very useful for refactoring a synchronous
//operation without a lot of code changes.
}
//Here's the callback, which is invoked properly by the runtime when the thread is complete
public void TaskComplete(IASyncResult ar)
{
//calling EndInvoke on the same delegate, which is available in the AsyncResult,
//returns the return value of that delegate as if you'd called it synchronously.
var results = ar.AsyncDelegate.EndInvoke(ar);
//Now you can do something with those results.
}
Ambos modelos deberían funcionar bien para usted. Otras opciones incluyen la configuración de un evento, que luego es planteado por cada método cuando se completa. Funcionaría casi de la misma manera, ya que los eventos son en realidad delegados "multi-cast" con algo de sintaxis de azúcar.
Esto es exactamente lo que estoy buscando. Sospeché que había algo como esto en el marco, simplemente no pude encontrarlo. – Mas