c# – 任务并行库中的任务如何影响ActivityID?

前端之家收集整理的这篇文章主要介绍了c# – 任务并行库中的任务如何影响ActivityID?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
在使用任务并行库之前,我经常使用CorrelationManager.ActivityId跟踪多个线程的跟踪/错误报告.

ActivityId存储在Thread Local Storage中,所以每个线程都有自己的副本.这个想法是当您启动一个线程(活动)时,您将分配一个新的ActivityId. ActivityId将被写入到具有任何其他跟踪信息的日志中,从而可以为单个“活动”列出跟踪信息.这对于WCF非常有用,因为ActivityId可以转移到服务组件.

以下是我正在谈论的例子:

static void Main(string[] args)
{
    ThreadPool.QueueUserWorkItem(new WaitCallback((o) =>
    {
        DoWork();
    }));
}

static void DoWork()
{
    try
    {
        Trace.CorrelationManager.ActivityId = Guid.NewGuid();
        //The functions below contain tracing which logs the ActivityID.
        CallFunction1();
        CallFunction2();
        CallFunction3();
    }
    catch (Exception ex)
    {
        Trace.Write(Trace.CorrelationManager.ActivityId + " " + ex.ToString());
    }
}

现在,使用TPL,我的理解是,多个任务共享线程.这是否意味着ActivityId容易被重新初始化中间任务(由另一个任务)?是否有新的机制来处理活动追踪?

解决方法

我进行了一些实验,结果是我的问题的假设是不正确的 – 使用TPL创建的多个任务不会同时在同一个线程上运行.

ThreadLocalStorage可以安全地使用.NET 4.0中的TPL,因为一次只能由一个任务使用一个线程.

任务可以同时共享线程的假设是基于我在DotNetRocks上听到的关于c#5.0的访问(对不起,我不记得那是哪个节目) – 所以我的问题可能(或可能不会)变得相关.

我的实验开始了许多任务,并记录了运行了多少任务,花费了多少时间以及消耗了多少线程.如果有人想重复,代码如下.

class Program
{
    static void Main(string[] args)
    {
        int totalThreads = 100;
        TaskCreationOptions taskCreationOpt = TaskCreationOptions.None;
        Task task = null;
        Stopwatch stopwatch = new Stopwatch();
        stopwatch.Start();
        Task[] allTasks = new Task[totalThreads];
        for (int i = 0; i < totalThreads; i++)
        {
            task = Task.Factory.StartNew(() =>
           {
               DoLongRunningWork();
           },taskCreationOpt);

            allTasks[i] = task;
        }

        Task.WaitAll(allTasks);
        stopwatch.Stop();

        Console.WriteLine(String.Format("Completed {0} tasks in {1} milliseconds",totalThreads,stopwatch.ElapsedMilliseconds));
        Console.WriteLine(String.Format("Used {0} threads",threadIds.Count));
        Console.ReadKey();
    }


    private static List<int> threadIds = new List<int>();
    private static object locker = new object();
    private static void DoLongRunningWork()
    {
        lock (locker)
        {
            //Keep a record of the managed thread used.
            if (!threadIds.Contains(Thread.CurrentThread.ManagedThreadId))
                threadIds.Add(Thread.CurrentThread.ManagedThreadId);
        }
        Guid g1 = Guid.NewGuid();
        Trace.CorrelationManager.ActivityId = g1;
        Thread.Sleep(3000);
        Guid g2 = Trace.CorrelationManager.ActivityId;
        Debug.Assert(g1.Equals(g2));
    }
}

输出(当然这取决于机器)是:

Completed 100 tasks in 23097 milliseconds
Used 23 threads

将taskCreationOpt更改为TaskCreationOptions.LongRunning提供了不同的结果:

Completed 100 tasks in 3458 milliseconds 
Used 100 threads
原文链接:https://www.f2er.com/csharp/97441.html

猜你在找的C#相关文章