Tamamlanmış bir Görev oluşturun


197

Tamamlanmış Task(değil Task<T>) oluşturmak istiyorum . Bunu yapmak için .NET'te yerleşik bir şey var mı?

İlgili bir soru: Tamamlanmış bir Görev oluşturma <T>


2
It seems like the answer I'm getting from everyone is that using a garbage value like this is the correct way. That there isn't a way to do this without the garbage value is disappointing -- oh well.Bunun ne gibi sorunları olduğunu düşünüyorsunuz? Tek bir önbellek kullanırsanız Task, tüm programınız fazladan bir miktar bellek alır. Bu hiçbir şey . Ayrıca, bunu yapmadan tamamlanmış bir görev yaratabilir, daha iyi olmazdı.
13'te

10
Hayal kırıklığımın fazladan bellek kullanmak zorunda kalmasıyla hiçbir ilgisi yok. Sadece kodun herhangi bir yerinde çöp değerleri zarif değildir.
Timothy Shields

1
Bugün ValueTasktamamlanmış görevler için (yani kodun esasen senkronize olması için zaten sahip olduğunuz değerler için) olduğunu unutmayın, bu da size bir tahsis tasarrufu sağlar.
nawfal

Yanıtlar:


247

Net (v4.6) en yeni sürümü sadece ekliyor, yerleşik bir Task.CompletedTask :

Task completedTask = Task.CompletedTask;

Bu özellik kilitsiz bir singleton olarak uygulanır, böylece neredeyse her zaman aynı tamamlanmış görevi kullanırsınız.


1
En yeni VS 14 CTP'yi kontrol ettim ve bir 4.5.3 projesi yarattı Task.CompletedTask, hala dahili.
Peter Ritchie

1
2. Ya en son CTP'yi (4 olan ve o siteden bağlanan) indirmediniz ya da 4.5.3 sürümünü belirtmediniz. İşte makinemde ne var . @PeterRitchie
i3arnon

Azure'daki Visual Studio 14 görüntüsünden bir VM oluşturdum.
Peter Ritchie


Mono 5.4.1.7 ile Mac OS X üzerinde çalışıyorum ve aynı hatayı alıyorum. Bunu nasıl düzeltebilirim?
Khaled Annajar

153

Task<T>örtük olarak dönüştürülebilir Task, bu yüzden tamamlanmış Task<T>(herhangi Tbir değerle) alın ve bunu kullanın. Gerçek bir sonucun bir yerlerde olduğu gerçeğini gizlemek için böyle bir şey kullanabilirsiniz.

private static Task completedTask = Task.FromResult(false);
public static Task CompletedTask()
{
    return completedTask;
}

Sonucu göstermediğimiz ve görev her zaman tamamlandığından, tek bir görevi önbelleğe alabileceğimizi ve yeniden kullanabileceğimizi unutmayın.

.NET 4.0 kullanıyorsanız ve sahip FromResultdeğilseniz, aşağıdakileri kullanarak kendiniz oluşturabilirsiniz TaskCompletionSource:

public static Task<T> FromResult<T>(T value)
{
    var tcs = new TaskCompletionSource<T>();
    tcs.SetResult(value);
    return tcs.Task;
}

8
4.0 kullanıyorsanız, TaskEx.FromResult'un yanı sıra WhenAll
Carl

@Servy FromResult (false) ve FromResult (true) 'dan ne değişir?
Francesco Bonizzi

3
@FrancescoB. Sonuca bakıyorsanız, sonucun boole değerini değiştirir. Sonucu görmezden gelirseniz, sonucun ne olduğu önemsizdir.
16'da

66

Bunu yapmak için tercih ettiğim yöntem, Task.WhenAll() argüman olmadan yapmaktır. MSDN belgelerine göre, "Sağlanan dizi / enumerable hiçbir görevleri içeriyorsa, dönen görev RanToCompletion durumuna hemen geçiş o arayana geri verdikten önce.". Kulağa istediğin gibi geliyor.

Güncelleştirme: Kaynağı Microsoft'un Referans Kaynağında buldum ; orada görebileceğinizi görebilirsiniz Görev.Ne zaman aşağıdakileri içerir:

return (tasks.Length == 0) ? // take shortcut if there are no tasks upon which to wait
            Task.CompletedTask :
            new WhenAllPromise(tasks);

Yani Task.CompletedTask gerçekten dahili, ancak hiçbir argüman olmadan WhenAll () çağrılarak ortaya çıkar.


9
kibirli hissettirirken, dokümanlardan destek var, bu yüzden bilmiyorum, biraz beğendim!
sara

2
Ben ve .NET 4.5.2 kısıtlamalı kodum için yeterince zarif. Teşekkürler!
Stas Ivanov

36

Kullanırdım Task.Delay(0). Dahili olarak, tamamlanmış bir önbelleğe alınmış örneğini döndürür Task<T>. Bu tam olarak şu anki yanıtın önerdiği şeydir, ancak şimdi bir örneği kendiniz önbelleğe almanız veya kodunuzda yetersiz çöp değerleriniz yoktur.

Sen kullanabilirsiniz düşünce olabilir Task.Yield()yerine, ancak sonucunu çıkıyor Task.Yield()olduğu değil bir alt tipi Tasksonucu oysa Task.Delay(0)olduğunu. Bu ikisi arasındaki ince farklardan biri.


30

Tamamlanmış bir geri dönmek için Task.FromResult'u (.NET 4.5'te ) kullanabilirsiniz Task<T>.

Eğer jenerik olmayana ihtiyacınız Taskvarsa, her zaman Task.FromResult(0)veya benzeri kullanabilirsiniz , çünkü Task<T>bir alt sınıfıdır Task.


11

Net 4.6 ve üstü kullanım için

return Task.CompletedTask;

Daha düşük sürümler için

return new Task(() => { });

3
4.6 öncesi yaklaşım için dikkatli olun! Görevi başlatmanız gerekir, aksi takdirde görev tamamlanmaz! return Task.Delay(0);Bunun yerine kullanmaya ne dersiniz ?
Miquel


0

Nasıl olur:

#pragma warning disable 1998
    public async Task emptyTask() {
    }
#pragma warning restore 1998

Sakıncası yoksa uyarı bastırma özelliğini dışarıda bırakabilirsiniz.


Bir yöntemi işaretlemenin async, kullanmasanız bile tüm durum makine aygıtını oluşturduğuna inanıyorum , bu nedenle boş bir görevi döndürmek düşük kaynak senaryoları için daha verimli.
Calvin Fisher
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.