如何确保一次只有1个线程可以访问DataTable [英] How to make sure only 1 thread has access to DataTable at a time

查看:70
本文介绍了如何确保一次只有1个线程可以访问DataTable的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个Windows控制台应用程序:

I have this Windows Console Application:

using System;
using System.Text;

namespace ThreadLockSample
{
    class Program
    {
        static void P1(System.Data.DataTable dt)
        {

            for (int i = 0; i < 100000; i++)
            {
                dt.Rows.Add(i);
            }
        }
        static void P2(System.Data.DataTable dt)
        {

            for (int i = 100000; i < 200000; i++)
            {
                dt.Rows.Add(i);
            }
        }

        static void Main(string[] args)
        {
            System.Data.DataTable dt = new System.Data.DataTable();
            for (int i = 0; i < 200; i++)
                dt.Columns.Add("Id " + i);

            System.Threading.Thread t1 = new System.Threading.Thread(() => P1(dt));
            System.Threading.Thread t2 = new System.Threading.Thread(() => P2(dt));
            t1.Start();
            t2.Start();
            t1.Join();
            t2.Join();
        }
    }
}

现在我正在传递数据表两个线程均可访问,但应用程序冻结-我该如何更改代码以消除此问题。

Now i am passing a DataTable accessible to both threads but the app freezes - how can i change my code to remove this issue.

推荐答案

在运行此应用程序时,您不会陷入僵局。相反,您会收到一条错误消息,指出 DataTable 中的某些数据已损坏,因为 DataTable 本身具有一些内部并发检查

When running this application, you won't get a deadlock. Instead you get an error stating that some data is corrupted within the DataTable because the DataTable itself has some internal checks for concurrency.

我想这个应用程序是您实际应用程序的简单版本。您可以采取一些步骤来改进程序:

I suppose this application is a simpler version of your real app. There are a couple of steps you can take to improve your program:


  • 避免使用共享数据进行多线程处理

使用共享数据进行多线程很难。您可以简化程序,以便不需要任何共享数据吗?也许您可以并行运行两个操作,返回一个结果,然后合并这些结果。

Multithreading with shared data is hard. Can you simplify your program so that you don't need any shared data? Maybe you can run two operations in parallel, return a result and then merge those results. This would safe you from a lot of potential problems.

如果不可能,则可以执行以下操作:

If that's not possible you can do the following:


  • 添加锁

您创建这样的锁对象:

private static object _lock = new object();

现在,您将数据表的调用包含在以下内容中:

And now you surround calls to your datatable with:

lock (_lock)
{
    dt.Rows.Add(i);
}




  • 不要直接使用线程。而是使用Task Parallel Library:

  • A Task 对象是一个智能包装器围绕一个线程。建议使用任务。

    A Task object is an intelligent wrapper around a Thread. Using Tasks is recommended.

    Task t1 = Task.Run(() => P1(dt));
    Task t2 = Task.Run(() => P2(dt));
    
    Task.WaitAll(t1, t2);
    



    UPDATE



    因为原来的问题现在从死锁变为冻结,还需要考虑其他几件事。

    UPDATE

    Since the original question now changed from deadlock to freezes, there are a couple of other things you need to consider.

    在控制台应用程序中,您将始终必须等待直到两个任务完成。这种等待将冻结您的UI。当然,您可以使用计时器等聪明的方法来检查任务是否已完成,但是控制台应用程序确实不适用于这种情况。

    In a console application, you will always have to wait at some point until your two tasks finish. This waiting will freeze your UI. Off course you can use clever things like a Timer to check if the tasks are finished or something but a console application really isn't meant for a situation like this.

    如果但是,您的应用程序实际上是WinForms或WPF应用程序,您应该使用在C#5中添加了新的async / await关键字的异步代码来使用它们。它们与Tasks完美配合,可以在UI保持响应的同时在另一个线程上运行代码。任务完成后,结果将重新合并到您的UI线程上,并且用户保留响应式应用程序。

    If however, your app is actually a WinForms or WPF app you should look at using asynchronous code with the new async/await keywords added in C# 5. They work perfectly with Tasks and they let you run code on another thread while the UI keeps responsive. When the Task finishes, the result is merged back on your UI thread and the user keeps a responsive app.

    有关异步/等待的更多信息,您可以从这里开始: 使用Async和Await(C#和Visual Basic)进行异步编程

    For more information on async/await, you can start here: Asynchronous Programming with Async and Await (C# and Visual Basic)

    这篇关于如何确保一次只有1个线程可以访问DataTable的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆