AFAIK, yang diketahuinya adalah bahwa pada titik tertentu, metode SetResult
atau SetException
dipanggil untuk menyelesaikan Task<T>
eksposur melalui Task
propertinya.
Dengan kata lain, ia bertindak sebagai produsen untuk Task<TResult>
dan penyelesaiannya.
Saya melihat contohnya di sini :
Jika saya memerlukan cara untuk menjalankan Func asynchronous dan memiliki Tugas untuk mewakili operasi itu.
public static Task<T> RunAsync<T>(Func<T> function)
{
if (function == null) throw new ArgumentNullException(“function”);
var tcs = new TaskCompletionSource<T>();
ThreadPool.QueueUserWorkItem(_ =>
{
try
{
T result = function();
tcs.SetResult(result);
}
catch(Exception exc) { tcs.SetException(exc); }
});
return tcs.Task;
}
Yang dapat digunakan * jika saya tidak memiliki Task.Factory.StartNew
- Tapi aku tidak memiliki Task.Factory.StartNew
.
Pertanyaan:
Dapatkah seseorang tolong jelaskan dengan contoh skenario yang berhubungan langsung dengan TaskCompletionSource
dan bukan dengan situasi hipotetis di mana saya tidak punya Task.Factory.StartNew
?
c#
.net
.net-4.0
task-parallel-library
taskcompletionsource
Royi Namir
sumber
sumber
Jawaban:
Saya kebanyakan menggunakannya ketika hanya API berbasis acara yang tersedia ( misalnya soket Windows Phone 8 ):
Jadi ini sangat berguna ketika digunakan bersama dengan
async
kata kunci C # 5 .sumber
SomeApiWrapper
menunggu di suatu tempat, sampai penerbit mengangkat acara yang menyebabkan tugas ini selesai?Microsoft.Bcl.Async
paket pada NuGet yang memungkinkanasync/await
kata kunci dalam proyek .NET 4.0 (VS2012 dan lebih tinggi direkomendasikan).Dalam pengalaman saya,
TaskCompletionSource
sangat bagus untuk membungkus pola asinkron lama dengan pola modernasync/await
.Contoh paling bermanfaat yang bisa saya pikirkan adalah ketika bekerja dengannya
Socket
. Ini memiliki pola APM dan EAP lama, tetapi bukanawaitable Task
metode ituTcpListener
danTcpClient
miliki.Saya pribadi punya beberapa masalah dengan
NetworkStream
kelas dan lebih suka yang mentahSocket
. Karena saya juga menyukaiasync/await
polanya, saya membuat kelas ekstensiSocketExtender
yang menciptakan beberapa metode ekstensi untukSocket
.Semua metode ini digunakan
TaskCompletionSource<T>
untuk membungkus panggilan asinkron seperti:Saya meneruskan
socket
keBeginAccept
metode sehingga saya mendapatkan sedikit peningkatan kinerja dari kompiler tidak harus mengerek parameter lokal.Maka keindahan dari semuanya:
sumber
Begin.. End...
pernyataan.Bagi saya, skenario klasik untuk digunakan
TaskCompletionSource
adalah ketika mungkin bahwa metode saya tidak perlu harus melakukan operasi yang memakan waktu. Apa yang memungkinkan kami lakukan adalah memilih kasus tertentu di mana kami ingin menggunakan utas baru.Contoh yang baik untuk ini adalah ketika Anda menggunakan cache. Anda dapat memiliki
GetResourceAsync
metode, yang terlihat di cache untuk sumber daya yang diminta dan kembali sekaligus (tanpa menggunakan utas baru, dengan menggunakanTaskCompletionSource
) jika sumber itu ditemukan. Hanya jika sumber daya tidak ditemukan, kami ingin menggunakan utas baru dan mengambilnya menggunakanTask.Run()
.Contoh kode dapat dilihat di sini: Cara menjalankan kode secara kondisional menggunakan tugas
sumber
Task.FromResult
untuk melakukan ini. Tentu saja, jika Anda menggunakan 4.0 dan tidak memilikiTask.FromResult
apa yang Anda gunakan untuk menggunakan TCS adalah menulis sendiriFromResult
.Task.FromResult
hanya tersedia sejak .NET 4.5. Sebelum itu, itulah cara untuk mencapai perilaku ini.Task.Run
, yang menunjukkan 4.5+. Dan komentar saya sebelumnya secara khusus membahas .NET 4.0.Dalam posting blog ini , Levi Botelho menjelaskan cara menggunakan
TaskCompletionSource
untuk menulis bungkus asinkron untuk Proses sehingga Anda dapat meluncurkannya dan menunggu penghentiannya.dan penggunaannya
sumber
Sepertinya tidak ada yang disebutkan, tapi saya kira tes unit juga dapat dianggap cukup nyata .
Saya menemukan
TaskCompletionSource
berguna ketika mengejek ketergantungan dengan metode async.Dalam program aktual yang sedang diuji:
Dalam tes unit:
Lagi pula, penggunaan TaskCompletionSource ini tampaknya merupakan kasus lain dari "objek Tugas yang tidak mengeksekusi kode".
sumber
TaskCompletionSource digunakan untuk membuat objek Tugas yang tidak mengeksekusi kode. Dalam skenario dunia nyata, TaskCompletionSource sangat ideal untuk operasi terikat I / O. Dengan cara ini, Anda mendapatkan semua manfaat tugas (misalnya nilai pengembalian, kelanjutan, dll) tanpa memblokir utas selama operasi. Jika "fungsi" Anda adalah operasi terikat I / O, tidak disarankan untuk memblokir utas menggunakan Tugas baru . Alih-alih, menggunakan TaskCompletionSource , Anda dapat membuat tugas budak untuk menunjukkan kapan operasi terikat I / O Anda selesai atau ada kesalahan.
sumber
Ada contoh dunia nyata dengan penjelasan yang layak dalam posting ini dari blog "Pemrograman Paralel dengan .NET" . Anda benar-benar harus membacanya, tetapi inilah ringkasannya.
Posting blog menunjukkan dua implementasi untuk:
Implementasi pertama yang ditunjukkan didasarkan pada
Task<>
dan memiliki dua kelemahan utama. Pos implementasi kedua berlanjut untuk mengurangi ini dengan menggunakanTaskCompletionSource<>
.Inilah implementasi kedua:
sumber
await Task.Delay(millisecondsDelay); action(); return;
atau (dalam. Net 4.0)return Task.Delay(millisecondsDelay).ContinueWith( _ => action() );
Ini mungkin terlalu menyederhanakan hal-hal tetapi sumber TaskCompletion memungkinkan seseorang untuk menunggu acara. Karena tcs.SetResult hanya diatur setelah peristiwa terjadi, pemanggil dapat menunggu tugas.
Tonton video ini untuk wawasan lebih lanjut:
http://channel9.msdn.com/Series/Three-Essential-Tips-for-Async/Lucian03-TipsForAsyncThreadsAndDatabinding
sumber
Skenario dunia nyata yang pernah saya gunakan
TaskCompletionSource
adalah ketika mengimplementasikan antrian unduhan. Dalam kasus saya jika pengguna memulai 100 unduhan, saya tidak ingin memadamkan semuanya sekaligus dan alih-alih mengembalikan tugas yang sudah ditentukan, saya mengembalikan tugas yang dilampirkanTaskCompletionSource
. Setelah unduhan selesai, utas yang berfungsi, antrian menyelesaikan tugas.Konsep kuncinya di sini adalah bahwa saya melakukan decoupling ketika seorang klien meminta sebuah tugas dimulai dari saat ia benar-benar dimulai. Dalam hal ini karena saya tidak ingin klien harus berurusan dengan manajemen sumber daya.
perhatikan bahwa Anda dapat menggunakan async / menunggu di .net 4 selama Anda menggunakan kompiler C # 5 (VS 2012+) lihat di sini untuk lebih jelasnya.
sumber
Saya sudah terbiasa
TaskCompletionSource
menjalankan Tugas sampai dibatalkan. Dalam hal ini adalah pelanggan ServiceBus yang biasanya ingin saya jalankan selama aplikasi berjalan.sumber
TaskCompletionSource
adalah untuk Tugas sepertiWaitHandle
untuk Thread. Jadi kita dapat menggunakanTaskCompletionSource
untuk melakukan pensinyalan yang tepat .Contohnya adalah jawaban saya untuk pertanyaan ini: Penundaan ContentDialog setelah OK diklik
sumber