.NET TPL lambdas和闭包 - 这段代码会起作用吗

时间:2011-04-14 22:55:55

标签: multithreading c#-4.0 closures task-parallel-library

所以我正在尝试使用.NET 4.0中的TPL功能,并且有一些像这样的代码(不要笑):

/// <summary>Fetches a thread along with its posts.  Increments the thread viewed counter.</summary>
public Thread ViewThread(int threadId)
{
   // Get the thread along with the posts
   Thread thread = this.Context.Threads.Include(t => t.Posts)
       .FirstOrDefault(t => t.ThreadID == threadId);

   // Increment viewed counter
   thread.NumViews++;
   Task.Factory.StartNew(() =>
   {
       try {
           this.Context.SaveChanges();
       }
       catch (Exception ex) {
           this.Logger.Error("Error viewing thread " + thread.Title, ex);
       }

       this.Logger.DebugFormat(@"Thread ""{0}"" viewed and incremented.", thread.Title);
   });

   return thread;
}

所以我对lambda的直接关注是this.Context(我的实体框架datacontext成员),this.Logger(记录器成员)和线程(用于记录器调用)。通常在QueueUserWorkItem()天,我认为这些需要作为状态对象的一部分传递给委托。关闭是否会让我失去帮助呢?

另一个问题是此例程所使用的类型实现了IDisposable,因此位于using语句中。所以如果我做的话......

using (var bl = new ThreadBL()) {
            t = bl.ViewThread(threadId);
        }

...我是否会在dispose()调用和TPL调用lambda之间创建一场竞赛?

目前我看到上下文将数据保存回我的数据库但没有记录 - 也没有例外。这可能是我配置的事情,但关于这段代码的一些感觉很奇怪。我不想在其他线程中有未处理的异常。欢迎任何意见!

1 个答案:

答案 0 :(得分:0)

至于关于闭包的问题,​​是的,这正是关闭的问题。您不必担心传递状态,而是从任何外部上下文中捕获它并将其复制到编译器提供的类中,这也是定义闭包方法的位置。编译器在这里做了很多魔术,让你的生活变得简单。如果你想了解更多我强烈建议在深度中选择Jon Skeet的C#。关于闭包的章节实际上是available here

至于您的具体实现,它不会主要用于您提到的确切问题:任务将在ViewThread结束时安排,但在您的ThreadBL实例被处置之前可能无法执行的。