SORU
22 Mart 2014, CUMARTESİ


Nasıl bir Görev üzerinde senkron devamı engelleyebilir miyim?

İstekleri için bekleyen cevaplar için Tasktabanlı bir API sağlar (soket ağ) bazı kütüphane kodu TaskCompletionSource<T> dayanarak. Ancak, VUK bunun imkansız senkron devamı engellemek gibi görünüyor bir sıkıntı yok. Yapardımgibiyapabilmek için:

  • arayanlar TaskContinuationOptions.ExecuteSynchronously ile bağlamak için izin vermemelidir TaskCompletionSource<T> bir söyle ya
  • TaskContinuationOptions.ExecuteSynchronously yerine havuza girmeden göz ardı edilmesini belirten bir şekilde sonuç (SetResult / TrySetResult ) ayarlayın

Özellikle, sorun var olduğu gelen veriler kayıt altına alınıyor tarafından özel bir okuyucu, ve eğer bir arayan edebilir Ekle TaskContinuationOptions.ExecuteSynchronously uzatabilir okuyucu (etkileyen sadece onları). Daha önce olup olmadığını tespit eden bazı hackery tarafından bu yerinde çalıştımherhangi birdevamı için vardır, ve eğer onlar iter tamamlanması üzerine ThreadPool, ancak bu önemli etkisi ise arayan var doymuş işlerini sıraya kadar tamamlanması değil, elde işlenmiş bir zamanında moda. Eğer Task.Wait() (veya benzeri) kullanıyorsanız, o zaman aslında kendilerini çıkmaz. Aynı şekilde, bu okuyucu işçiler kullanmak yerine özel bir konu üzerinde olmasıdır.

Ben denemek ve TRAFİK ekibi dırdır önce; bir seçenek mi kaçırdım?

Önemli noktalar:

  • Dış arayanlar benim konuyu kaçırmak mümkün olmak istemiyorum
  • Havuz doymuş olduğunda çalışması gereken bir uygulama olarak ThreadPool kullanamam

Aşağıdaki örnek çıktı (sipariş zamanlama bağlı olarak değişebilir) üretir:

Continuation on: Main thread
Press [return]
Continuation on: Thread pool

Sorun rastgele bir numaradan bir devamı başardı gerçektir "Ana iş parçacığı". Gerçek kodda, bu birincil okuyucu rahatsız olur; 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();
    }
}

CEVAP
23 Mart 2014, Pazar


Yeni .NET 4.6:

.4.6TaskCreationOptionsyeni bir içerir NET: RunContinuationsAsynchronously.


Yansıma özel alanlarına erişim için kullanmaya istekli olduğuna göre...

Tüm devamı inlined neden olacak olan TASK_STATE_THREAD_WAS_ABORTED bayrağı ile Kıbrıslı Türklerin Görev işareti olabilir.

const int TASK_STATE_THREAD_WAS_ABORTED = 134217728;

var stateField = typeof(Task).GetField("m_stateFlags", BindingFlags.NonPublic | BindingFlags.Instance);
stateField.SetValue(task, (int) stateField.GetValue(task) | TASK_STATE_THREAD_WAS_ABORTED);

Düzenleme:

Yansıtma yayma yerine, ifadeler kullanmanızı öneririm. Bu çok daha okunabilir ve PCL uyumlu olma avantajı vardır:

var taskParameter = Expression.Parameter(typeof (Task));
const string stateFlagsFieldName = "m_stateFlags";
var setter =
    Expression.Lambda<Action<Task>>(
        Expression.Assign(Expression.Field(taskParameter, stateFlagsFieldName),
            Expression.Or(Expression.Field(taskParameter, stateFlagsFieldName),
                Expression.Constant(TASK_STATE_THREAD_WAS_ABORTED))), taskParameter).Compile();

Yansıma kullanmadan:

Eğer ilgilenen varsa, Yansıma olmadan bunu yapmak için bir yol buldum ama biraz "" de, ve tabii ki taşır gözardı olmayan perf bir ceza . kirli

try
{
    Thread.CurrentThread.Abort();
}
catch (ThreadAbortException)
{
    source.TrySetResult(123);
    Thread.ResetAbort();
}

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Cristina Landa

    Cristina Lan

    28 Ocak 2010
  • humanHardDrive

    humanHardDri

    16 Mart 2011
  • Whizzpopping

    Whizzpopping

    10 Kasım 2005