Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用LINQ到SQL的多线程_C#_.net_Multithreading_Linq To Sql - Fatal编程技术网

C# 使用LINQ到SQL的多线程

C# 使用LINQ到SQL的多线程,c#,.net,multithreading,linq-to-sql,C#,.net,Multithreading,Linq To Sql,我正在写一个WinForms应用程序。我正在从数据库中提取数据,对该数据集执行一些操作,然后计划将其保存回数据库。我使用LINQtoSQL来执行对数据库的查询,因为我只关心数据库中的一个表,所以我不想为此实现整个ORM 我让它从数据库中提取数据集。然而,数据集相当大。因此,目前我尝试将数据集分成4个大小相对相等的列表(List) 然后,我有一个单独的后台工作人员来运行这些列表,执行操作并报告其进度。我计划在所有4名背景工作人员处理完他们的部分后,将这些部分合并成一个大列表 但是,在后台工作人员处

我正在写一个WinForms应用程序。我正在从数据库中提取数据,对该数据集执行一些操作,然后计划将其保存回数据库。我使用LINQtoSQL来执行对数据库的查询,因为我只关心数据库中的一个表,所以我不想为此实现整个ORM

我让它从数据库中提取数据集。然而,数据集相当大。因此,目前我尝试将数据集分成4个大小相对相等的列表(
List

然后,我有一个单独的后台工作人员来运行这些列表,执行操作并报告其进度。我计划在所有4名背景工作人员处理完他们的部分后,将这些部分合并成一个大列表

但是,在后台工作人员处理他们的唯一列表时,我不断收到一个错误。即使对象已转换为列表对象,它们是否仍保持与LINQ to SQL的DataContext的关联?有没有办法解决这个问题?我在多线程方面的经验很少,所以如果我在这方面完全错了,请告诉我

谢谢各位。如果您需要任何代码片段或任何其他信息,请询问

编辑:Oops。我完全忘了给出错误消息。在DataContext designer.cs中,它给出了一个错误
一个已经添加了相同键的项。
SendPropertyChanging
函数上

private void Setup(){
    List<MyObject> quarter1 = _listFromDB.Take(5000).ToList();
    bgw1.RunWorkerAsync();
}

private void bgw1_DoWork(object sender, DoWorkEventArgs e){
    e.Result = functionToExecute(bgw1, quarter1);
} 

private List<MyObject> functionToExecute(BackgroundWorker caller, List<MyObject> myList)
    {
        int progress = 0;
        foreach (MyObject obj in myList)
        {
            string newString1 = createString();
            obj.strText = newString;
            //report progress here
            caller.ReportProgress(progress++);
        }
        return myList;
    }
private void Setup(){
List quarte1=_listFromDB.Take(5000.ToList();
bgw1.RunWorkerAsync();
}
私有无效bgw1_DoWork(对象发送方,DoWorkEventArgs e){
e、 结果=功能执行(bgw1,第1季度);
} 
私有列表函数执行(BackgroundWorker调用者,列表myList)
{
int progress=0;
foreach(myList中的MyObject对象)
{
字符串newString1=createString();
obj.strText=新闻字符串;
//在此报告进展情况
caller.ReportProgress(progress++);
}
返回myList;
}

这同一个函数由所有四个worker调用,并根据调用函数的worker为myList提供了不同的列表。

首先,我真的不明白为什么需要多个worker线程。(这些列表是在单独的数据库/表/服务器中吗?如果有4个列表,你真的想显示4个进度条吗?还是你想把这些进度报告合并成一个奇怪的进度条:D

private void Setup(){
    List<MyObject> quarter1 = _listFromDB.Take(5000).ToList();
    bgw1.RunWorkerAsync();
}

private void bgw1_DoWork(object sender, DoWorkEventArgs e){
    e.Result = functionToExecute(bgw1, quarter1);
} 

private List<MyObject> functionToExecute(BackgroundWorker caller, List<MyObject> myList)
    {
        int progress = 0;
        foreach (MyObject obj in myList)
        {
            string newString1 = createString();
            obj.strText = newString;
            //report progress here
            caller.ReportProgress(progress++);
        }
        return myList;
    }
此外,您正试图加快数据库更新的处理速度,但您不会将linq发送到sql任何保存,因此您不是真正的批处理事务,您只会在一个大事务中保存最后的所有内容,这真的是您的目标吗?进度条只会在100%停止,然后在sql端花费大量时间。

只需创建一个后台线程并同步处理所有内容,但每两行批处理一个保存事务(我建议每1000行批处理一次,但您应该尝试一下),即使有数百万行,也会很快

如果您确实需要此多线程解决方案: “已添加另一个具有相同密钥的blabla”错误表明您正在将同一项添加到多个“MyList”中,或将同一项添加到同一列表中两次,否则会出现任何错误?

使用,您可以利用多个CPU核来处理数据。但是,如果您的应用程序将在单核CPU上运行,则将数据拆分为和平并不会给您带来性能方面的好处,相反,它会导致一些上下文冲突头顶上的安格


希望它能有所帮助,因为真正的答案还没有公布,我将试一试。 考虑到您没有显示任何LINQ到SQL代码(没有使用DataContext),我将有根据地猜测DataContext是在线程之间共享的,例如:

using (MyDataContext context = new MyDataContext())
{
    // this is just some random query, that has not been listed - ToList()
    // thus query execution is defered. listFromDB = IQueryable<>
    var listFromDB = context.SomeTable.Where(st => st.Something == true);

    System.Threading.Tasks.Task.Factory.StartNew(() => 
    {
        var list1 = listFromDB.Take(5000).ToList(); // runs the SQL query
        // call some function on list1
    });

    System.Threading.Tasks.Task.Factory.StartNew(() => 
    {
        var list2 = listFromDB.Take(5000).ToList(); // runs the SQL query
        // call some function on list2
    });
}
使用(MyDataContext=newmydatacontext())
{
//这只是一些尚未列出的随机查询-ToList()
//因此,查询执行被推迟
var listFromDB=context.SomeTable.Where(st=>st.Something==true);
System.Threading.Tasks.Task.Factory.StartNew(()=>
{
var list1=listFromDB.Take(5000).ToList();//运行SQL查询
//调用列表1上的某个函数
});
System.Threading.Tasks.Task.Factory.StartNew(()=>
{
var list2=listFromDB.Take(5000).ToList();//运行SQL查询
//调用列表2中的某个函数
});
}
现在,您得到的错误-
已经添加了一个具有相同密钥的项。
-是因为DataContext对象不是线程安全的。!很多事情都发生在后台-DataContext必须从SQL加载对象,跟踪它们的状态,等等。这是引发错误的后台工作(因为每个线程都在运行查询,所以可以访问DataContext)

至少这是我个人的经验。在多个线程之间共享DataContext时遇到相同的错误。在这种情况下,您只有两个选项:

1) 在启动线程之前,对查询调用
.ToList()
,使
listFromDB
不是一个
IQueryable
,而是一个实际的
List
。这意味着查询已经运行,线程操作的是一个实际的列表,而不是DataContext

2) 将DataContext定义移动到每个线程中。因为DataContext不再共享,所以不再有错误


第三种选择是将场景重新写入其他内容,就像您所做的那样(例如,使所有内容在单个后台线程上保持顺序)

对象引用将添加到列表中,因此它们将保持关联。尝试映射对象。能否将收到的错误作为编辑添加到问题中?列表正在存储引用t