加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-15 18:04:19 所属栏目:百科 来源:网络整理
导读:在使用任务并行库之前,我经常使用CorrelationManager.ActivityId跟踪多个线程的跟踪/错误报告. ActivityId存储在Thread Local Storage中,所以每个线程都有自己的副本.这个想法是当您启动一个线程(活动)时,您将分配一个新的ActivityId. 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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读