Ho un metodo asincrono dopo il completamento del quale desidero eseguire un altro metodo. Funziona bene se chiamo semplicemente il metodo e aggiungo .ContinueWith()Creare un'attività Cold Awaitable
Tuttavia, ho un nuovo requisito che è quello di avviare l'attività solo se sono in grado di aggiungerlo a un dizionario concorrente.
desidero costruire il compito, tentare di aggiungere e poi avviare l'attività
Tuttavia, sembra che Task.Start() completa immediatamente l'attività che causa l'azione continuerà a funzionare e le eventuali attese a .. non aspettare.
qualcuno può spiegare perché questo accade e il modo corretto per raggiungere il mio obiettivo?
namespace UnitTestProject2
{
[TestClass]
public class taskProblem
{
[TestMethod]
public void Test()
{
CancellationTokenSource cancel = new CancellationTokenSource();
ConcurrentDictionary<Guid, Task> tasks = new ConcurrentDictionary<Guid,Task>();
Guid id = Guid.NewGuid();
Task t = new Task(async() => await Get(), cancel.Token);
t.ContinueWith(Complete);
if (tasks.TryAdd(id, t))
{
t.Start();
}
else
{
//another thread is stopping stuff dont start new tasks
}
t.Wait(); //expected to wait for the get function to complete
Console.WriteLine("end test");
}
public async Task Get()
{
Console.WriteLine("start task");
await Task.Delay(10000);
Console.WriteLine("end task");
}
public void Complete(Task t)
{
Console.WriteLine("Complete");
}
}
}
uscita:
start task
end test
Complete
risultato atteso:
start task
end task
Complete
end test
Aggiornamento: Sembra non v'è alcun modo per creare una nuova attività, che non si avvia immediatamente o completa subito su Task.Start?
Qual è il vero problema che stai cercando di risolvere?Il requisito non ha senso e il wrapping di Task a due livelli non aiuta. Non c'è * mai * un buon motivo per creare attività a freddo e chiamare 'Start'. Inoltre, non c'è motivo di racchiudere 'Get' che già restituisce un'attività in esecuzione in un altro. Basta scrivere 'Task t = Get();'. Per quanto riguarda il requisito, non ha senso. È sempre possibile aggiungere un nuovo elemento a un dizionario concorrente poiché in effetti si sta creando un nuovo codice Guida per esso. –
Sembra che tu stia passando un delegato asincrono nel costruttore 'Task' che non attenderà il completamento dell'attività da 'Get'. Perché stai provando a racchiudere la chiamata in "Get" in un'altra attività? – Lee
l'app reale invia notifiche push da una coda e ha un metodo Stop() (chiamato da un altro thread) per interrompere l'avvio di nuove attività. In questo caso ho bisogno del task non avviato in modo da poterlo aggiungere al dizionario simultaneo in modo thread-safe. ovviamente ci sono altri modi per farlo, che sarò costretto a usare se non riesco a capirlo. – Ewan