In .NET 4.5 gibt es Task.Delay
Wie kann ich dasselbe in .NET 4.0 tun?
In .NET 4.5 gibt es Task.Delay
Wie kann ich dasselbe in .NET 4.0 tun?
Thread.Sleep
in Ihrem Code ist fast immer ein Fehler.
Antworten:
Mit a können Sie Timer
eine Delay
Methode in 4.0 erstellen :
public static Task Delay(double milliseconds)
{
var tcs = new TaskCompletionSource<bool>();
System.Timers.Timer timer = new System.Timers.Timer();
timer.Elapsed+=(obj, args) =>
{
tcs.TrySetResult(true);
};
timer.Interval = milliseconds;
timer.AutoReset = false;
timer.Start();
return tcs.Task;
}
Callback()
Definition verwenden Dispatcher.BeginInvoke()
?
TrySetResult
nie aufgerufen.
Timer
Klasse behandelt dies speziell intern, um sicherzustellen, dass Benutzer nicht während ihrer gesamten Lebensdauer an einem Verweis darauf festhalten müssen. Solange der Timer gerade ausgeführt wird, fügt er an einem verwurzelten Speicherort einen Verweis auf sich selbst hinzu und entfernt ihn dann, wenn er nicht mehr ausgeführt wird.
Verwenden Sie das Microsoft.Bcl.Async- Paket von NuGet TaskEx.Delay
.
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static void Main()
{
Delay(2000).ContinueWith(_ => Console.WriteLine("Done"));
Console.Read();
}
static Task Delay(int milliseconds)
{
var tcs = new TaskCompletionSource<object>();
new Timer(_ => tcs.SetResult(null)).Change(milliseconds, -1);
return tcs.Task;
}
}
Aus dem Abschnitt Implementieren von Task.Delay in 4.0
object
den Wert seiner ToString
Methode ausgibt . Beachten Sie, dass er dies und keine anderen Methoden außerhalb der Bibliothek in seiner tatsächlichen Implementierung verwendet, sondern nur die Beispielfunktion, mit der es getestet wird.
Unten finden Sie den Code und das Beispielkabel für eine stornierbare Task.Delay-Implementierung. Sie interessieren sich wahrscheinlich für die Delay
Methode:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DelayImplementation
{
class Program
{
static void Main(string[] args)
{
System.Threading.CancellationTokenSource tcs = new System.Threading.CancellationTokenSource();
int id = 1;
Console.WriteLine(string.Format("Starting new delay task {0}. This one will be cancelled.", id));
Task delayTask = Delay(8000, tcs.Token);
HandleTask(delayTask, id);
System.Threading.Thread.Sleep(2000);
tcs.Cancel();
id = 2;
System.Threading.CancellationTokenSource tcs2 = new System.Threading.CancellationTokenSource();
Console.WriteLine(string.Format("Starting delay task {0}. This one will NOT be cancelled.", id));
var delayTask2 = Delay(4000, tcs2.Token);
HandleTask(delayTask2, id);
System.Console.ReadLine();
}
private static void HandleTask(Task delayTask, int id)
{
delayTask.ContinueWith(p => Console.WriteLine(string.Format("Task {0} was cancelled.", id)), TaskContinuationOptions.OnlyOnCanceled);
delayTask.ContinueWith(p => Console.WriteLine(string.Format("Task {0} was completed.", id)), TaskContinuationOptions.OnlyOnRanToCompletion);
}
static Task Delay(int delayTime, System.Threading.CancellationToken token)
{
TaskCompletionSource<object> tcs = new TaskCompletionSource<object>();
if (delayTime < 0) throw new ArgumentOutOfRangeException("Delay time cannot be under 0");
System.Threading.Timer timer = null;
timer = new System.Threading.Timer(p =>
{
timer.Dispose(); //stop the timer
tcs.TrySetResult(null); //timer expired, attempt to move task to the completed state.
}, null, delayTime, System.Threading.Timeout.Infinite);
token.Register(() =>
{
timer.Dispose(); //stop the timer
tcs.TrySetCanceled(); //attempt to mode task to canceled state
});
return tcs.Task;
}
}
}
Sie können das Visual Studio Async CTP herunterladen und TaskEx.Delay verwenden
In vielen Fällen ist ein reines AutoResetEvent besser als ein Thread.Sleep () ...
AutoResetEvent pause = new AutoResetEvent(false);
Task timeout = Task.Factory.StartNew(()=>{
pause.WaitOne(1000, true);
});
hoffe, dass es hilft
Hier ist eine prägnante, zeitgesteuerte Implementierung mit ordnungsgemäßer Bereinigung:
var wait = new TaskCompletionSource<bool>();
using (new Timer(_ => wait.SetResult(false), null, delay, Timeout.Infinite))
await wait.Task;
Um diesen Code unter .NET 4.0 verwenden zu können, benötigen Sie das Microsoft.Bcl.Async NuGet-Paket.
await
Schlüsselwort ist Teil der C # -Sprache, die von der .NET Framework-Version getrennt ist. Das Problem ist, dass Task<T>
es nicht gibt GetAwaiter
, worauf es await
ankommt. Microsoft.Bcl.Async liefert dies. Ich habe meine Antwort aktualisiert, um das NuGet-Paket zu erwähnen.
TaskEx.Delay
prägnanter?