如何使方法线程安全 - C# [英] How do I make a method threadsafe - C#

查看:76
本文介绍了如何使方法线程安全 - C#的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述





我正在使用Parallel.ForEach读取文件,然后将处理过的信息插入数据库。有些情况下,当我存放类似数据的多个文件并保存到数据库时,在这种情况下我需要更新以前的记录而不是创建一个新记录。



Hi,

I'm using Parallel.ForEach to read files and then insert processed information into database. There may cases when multiple files my reside similar data and while saving to database, in this scenario I need to updated previous record instead of creating a new one.

Parallel.ForEach(files, (FileInfo datafile, ParallelLoopState state) =>
                {
                    if (errorCount > maxErrors)
                    {
                        iterationMaxErrorAchieved = true;
                        state.Stop();

                    }
                    else
                    {
                        ImportDataProcess(datafile);
                    }
                });










void ImportPolicyInternalProcess(FileInfo datafile)
        {
            try
            {
                XmlDocument xmldoc = new XmlDocument();
                using (FileStream stream = datafile.OpenRead())
                {
                    xmldoc.Load(stream);
                }

                //....some code...

                if (InsertData(xmldoc.DocumentElement, int value1ID, int value2ID))
                {
                    
                }

                processedPolicyFileCounter++;
            }
            catch (Exception E)
            {
                
            }
        }





所以在InsertData方法中我使用了enityframework,并且基于value1ID,value2ID的组合,在DB中创建了一个不同的记录。如果存在一个这样的记录,则InsertData方法需要使用最新信息集更新它。



它工作正常,直到我使用同步插入,即没有并行性。但现在它继续在数据库中创建记录,而不管数据库中是否存在组合。



请协助。



谢谢,

Abhishek



So in InsertData method I'm using enityframework and on basis of combination of value1ID, value2ID a distinct record is created in DB. If there exists one such record the InsertData method need to update it with latest information set.

It was working fine till the time I was using synchronous inserts i.e. no parallelism. But now it keeps on creating records in the database irrespective of the fact that the combination already exists in DB.

Kindly assist.

Thanks,
Abhishek

推荐答案

通常,您可以通过以下方式使您的方法成为线程安全的使用锁定语句包装关键部分(使用公共资源的代码)。在您的情况下,似乎关键部分是 InsertData 方法中的数据库访问。

Typically, you can make your method thread-safe, by wrapping the critical sections (the code that use the common resource) with a lock statement. In your case, it seems like the critical section is the DB access in the InsertData method.


使用锁定 在调用InserData之前。这样,您将确保只有1个线程将更新数据库。但它打败了Parallel.ForEach的必要性。然而,如果在InsertData之前发生了大量的数据处理,那么在Insert之前锁定应该比完整的顺序处理更好。
Use "lock" before calling InserData. This way you will be sure that only 1 thread will be updating the DB. But it beats the necessity of Parallel.ForEach. Nevertheless if there is lot of data processing happening before InsertData then lock just before Insert should give you better results than a complete sequential processing.


不仅仅是一个准时的解决方案我想暴露一些点应用多线程时必须考虑的事项。

1.真的有必要吗?尝试并行化自然的串行执行流程是不可能的。如果您的代码是这样,请不要这样做!

2.分析可以并行化的执行流程部分以及具有交互和需要仲裁的部分。将代码分成几部分,可以并行化的部分进入主线程模块,无法并行化的部分进入相互仲裁的互锁模块(具有锁定,互斥或信号量),具体取决于它们之间的交互(是的,仲裁也不是简单的锁定)。

3.考虑在CPU处理器(物理或超线程)之后,所有其他任务按顺序工作(切换速度非常快,看起来真的是并行执行,但是毫无疑问总是连续的),所以如果工作量没有划分外部资源访问,你将无法获得真正的好处(在这里,我必须在多任务处理上花费很少的话来使这个概念更加明确: 多任务系统在等待资源时实现其他方面的效率。:)是的,真正的一点是,如果我的代码正在等待资源,如磁盘或其他什么,为什么可以CPU在此期间做了别的事吗? I / O子系统和许多其他资源管理器被编码为在资源被请求资源时立即停止线程执行,以便在资源可用时开始执行另一个线程,即磁盘读取内存中的某些扇区。)

4.关于'线程安全'概念的最后一些话。这基本上可以表示为必须保留许多线程可以删除的覆盖。您可以理解它可能意味着很多或者什么都不是,因为如果从另一个线程更新,则每个不严格本地的变量都可以被删除,但也可以是磁盘写入或GUI更新。再次分析您的代码,检查变量,I / O等的访问冲突,并编写适当的保护(锁或其他)以避免冲突访问。这与操作系统在其资源上所做的仲裁相同... ...

我希望这可能会引起一些兴趣......
More than a punctual solution I would like to expose some points that have to be considered when multithreading is applied.
1. Is it really necessary? Trying to parallelize a naturally serial flow of execution is not possible. If your code is so, don't do it!
2. Analyze the parts of the execution flow that could be parallelized and those that have interaction and need arbitration. Divide your code in pieces, The part that can be parallelized goes in the 'main' thread module, the parts that could not be parallelized go in interlocked modules that are appropriately arbitrated (with locking, mutex or semaphores) depending on the interaction between them (yes also arbitration is not the simple locking).
3. Consider that after the processors of your CPU (physical or hyperthreaded) all other tasks work sequentially (switched very fast to seem really parallel execution, but with no doubt always serial), so if the load of work is not divided on external resources access you will get no real benefit (here I have to spend few words on multitasking to made more clear the concept: A multitasking system realize the most of its efficiency in doing something else when waiting for a resource. :) Yes the real point is if my code is waiting for a resource, as the disk or whatever, why can the CPU do something else in the meantime? I/O subsystem, and many other resource managers, are coded to stop thread execution immediately as soon as a resource is requested alllowing the OS to start execution of another thread while the resource become available, i.e. the disk reads some sectors in memory.)
4. Last some words about the 'thread safe' concept. This can basically be expressed as "whatever that can be trashed overwriting by many threads have to be preserved". You can understand that it could mean a lot or nothing, because every variable that is not strictly local to a thread can be 'trashed' if updated from another thread, but also a disk write or GUI update. Once again analyze your code, check access conflicts on variables, I/O etc, and code the opportune protections (locks, or whatever) to avoid conflicting access. This is in small the same arbitration that an OS does on its resources... :)
I hope this could be of some interest...


这篇关于如何使方法线程安全 - C#的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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