Task
İsteklere yönelik bekleyen yanıtlar için tabanlı bir API sağlayan bazı kitaplık (soket ağı) kodum var TaskCompletionSource<T>
. Bununla birlikte, eşzamanlı sürekliliği önlemenin imkansız görünmesi nedeniyle TPL'de bir sıkıntı var. Ne olur gibi yapabilmek için aşağıdakilerden biri geçerlidir:
TaskCompletionSource<T>
Arayanların bağlanmasına izin vermemesi gerektiğini söyleyinTaskContinuationOptions.ExecuteSynchronously
veya- sonucu (
SetResult
/TrySetResult
)TaskContinuationOptions.ExecuteSynchronously
göz ardı edilmesi gerektiğini belirten bir şekilde, bunun yerine havuzu kullanarak ayarlayın
Spesifik olarak, sahip olduğum sorun, gelen verilerin özel bir okuyucu tarafından işleniyor olması ve bir arayanın ekleyebilmesi TaskContinuationOptions.ExecuteSynchronously
durumunda okuyucuyu oyalayabilmesi (bu sadece onlardan daha fazlasını etkiliyor). Daha önce, herhangi bir sürekliliğin mevcut olup olmadığını tespit eden bazı bilgisayar korsanları tarafından bu sorunu çözmüştüm ve eğer varsa, tamamlamayı üzerine iter ThreadPool
, ancak bu, arayanın iş kuyruğunu doldurması durumunda önemli bir etkiye sahiptir, çünkü tamamlama işlenmeyecektir. zamanında. Eğer kullanıyorlarsa Task.Wait()
(veya benzerlerse), o zaman esasen kendilerini kilitleyeceklerdir. Aynı şekilde, okuyucunun işçi kullanmaktan ziyade özel bir ileti dizisinde olmasının nedeni de budur.
Yani; TPL ekibini denemeden ve dırdır etmeden önce: bir seçeneği kaçırıyor muyum?
Anahtar noktaları:
- Dışarıdan arayanların ileti dizimi ele geçirmesini istemiyorum
ThreadPool
Havuz doyduğunda çalışması gerektiğinden uygulama olarak kullanamıyorum
Aşağıdaki örnek çıktı üretir (sıralama zamanlamaya göre değişebilir):
Continuation on: Main thread
Press [return]
Continuation on: Thread pool
Sorun, rastgele arayanın "Ana ileti dizisi" üzerinde bir devam ettirmeyi başardığı gerçeğidir. Gerçek kodda, bu birincil okuyucuyu kesintiye uğratır; kötü şeyler!
Kod:
using System;
using System.Threading;
using System.Threading.Tasks;
static class Program
{
static void Identify()
{
var thread = Thread.CurrentThread;
string name = thread.IsThreadPoolThread
? "Thread pool" : thread.Name;
if (string.IsNullOrEmpty(name))
name = "#" + thread.ManagedThreadId;
Console.WriteLine("Continuation on: " + name);
}
static void Main()
{
Thread.CurrentThread.Name = "Main thread";
var source = new TaskCompletionSource<int>();
var task = source.Task;
task.ContinueWith(delegate {
Identify();
});
task.ContinueWith(delegate {
Identify();
}, TaskContinuationOptions.ExecuteSynchronously);
source.TrySetResult(123);
Console.WriteLine("Press [return]");
Console.ReadLine();
}
}
TaskCompletionSource
Doğrudan çağrıyı önlemek için kendi API'mi sarmaya çalışıyorumContinueWith
, çünkü ne neTaskCompletionSource
deTask
onlardan miras almaya uygun değil.