Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/70.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# SQL和C的线程问题,其中不同的线程获得相同的数目,但不应为';T_C#_Sql - Fatal编程技术网

C# SQL和C的线程问题,其中不同的线程获得相同的数目,但不应为';T

C# SQL和C的线程问题,其中不同的线程获得相同的数目,但不应为';T,c#,sql,C#,Sql,我的场景:表中有n个记录,线程试图访问该表。一个人必须得到第一个号码并删除它,其他人必须一个接一个地得到第二个、第三个等等 但问题是一些线程得到了相同的数目。我如何避免这种情况 我的代码: private void Form1_Load(object sender, EventArgs e) { for (int j = 1; j >= 10; j++) { Thread.Sleep(1000); ThreadStart StarterCon

我的场景:表中有n个记录,线程试图访问该表。一个人必须得到第一个号码并删除它,其他人必须一个接一个地得到第二个、第三个等等

但问题是一些线程得到了相同的数目。我如何避免这种情况

我的代码:

private void Form1_Load(object sender, EventArgs e)
{
    for (int j = 1; j >= 10; j++)
    {
        Thread.Sleep(1000);
        ThreadStart StarterCon = delegate { this.Start_new(sno); };
        Thread th = new Thread(StarterCon);
        th.Start();
    }
}

private void Start_new(int h)
{
    try
    {
        for (; ; )
        {
            using (SqlConnection ObjConn = new SqlConnection(ConnectionString))
            {
                ObjConn.Open();
                using (SqlDataAdapter ObjAda = new SqlDataAdapter("Select_BlockedNubmer", ObjConn))
                {
                    ObjAda.SelectCommand.CommandType = CommandType.StoredProcedure;
                    SqlParameter parm;

                    parm = ObjAda.SelectCommand.Parameters.Add("@id", SqlDbType.NVarChar);
                    parm.Value = h;
                    using (DataTable dtTable = new DataTable())
                    {
                        ObjAda.Fill(dtTable);
                    }
                }

                ObjConn.Close();
            }
            Thread.Sleep(500);
        }
    }
    catch { }
}
我的存储过程是

Create procedure [dbo].[Select_BlockedNubmer]
@id varchar(max)
as
begin
    set rowcount 1
    select * from BlockedNumber
    delete from BlockedNumber
    set rowcount 0
end
编辑:我尝试了以下存储过程。它工作正常,但读取数字非常慢:

ALTER procedure [dbo].[Select_BlockedNubmer]
@id varchar(max)
as
begin
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
begin transaction
set rowcount 1
select * from BlockedNumber
delete from BlockedNumber
set rowcount 0
commit transaction
end
你应使用:


事务确保两个线程无法访问数据的“中间”状态。假设你是线程X:你选择一个数字。一旦你这么做,这个号码就属于你,没有其他线程可以读取它。所有其他线程都必须等待您提交事务,然后才能读取它们的事务。这使您有机会在提交事务之前删除该号码,这样他们就不会看到它。

您将永远循环。在这个循环中,您反复执行一些非常昂贵的操作,这可能会导致太多的连接或其他奇怪的东西四处浮动

我的建议是:只创建一个
SqlConnection
对象。不要每0.5秒循环一次,而是减慢循环速度或对外部触发器作出反应。您还可以重用
SqlDataAdapter
对象以获得更好的性能

对于线程,可以使用
lock
或使用其他同步原语来防止争用情况。虽然所用库方法上的单个静态方法是线程安全的,但这并不意味着在调用它们之间,线程会干扰数据对象


更新:已编辑,因为一开始线程代码是模糊的。

如果您试图不加区分地选择和删除记录,并且看起来是这样,为什么不更改存储过程?返回所有记录,然后删除所有记录?为什么您需要选择1/delete 1(或者对于代码示例,选择1/delete all)的约束?你想完成什么?事实上,直到现在我才注意到:你的第一个循环从未执行过
j>=10
始终为false。。。你曾经运行过你的代码吗?哦,
sno
应该包含什么?这可能与“线程获得相同的编号”有关,存储过程中的
@id
似乎也未使用☺@Timwi:(在你之前的
sno
评论中):事实上,这个变量可能是问题的根源(紧挨着没有同步的线程)。@Abel:Mwahaha,我也可以编辑!:-DHm,不能代表下层选民说话,但公平地说,他没有流动的联系:他适当地处理了他们。@Timwi:这是正确的,但正如你所知,
Dispose
是一回事,但托管资源不会在处理时被清除,而是在下一个GC循环时被清除。此外,设置SqlConnection是一项非常昂贵的操作,可能需要数十或百分之一毫秒才能完成。它们根本不属于内部循环。最后,这是一个猜测,
SqlConnection
在内部使用池,当一次创建百分之一百的连接时,这可能会完全混淆,但这是一个猜测。@Timwi:haha,ahum,好吧,那么,数百,tx@anbuselvanmca:代码中存在的问题不仅仅是事务。请参阅原始问题下方的评论。并花一些时间更新代码以反映您当前的情况,因为这不可能是准确的。在SQL2005及更高版本上,您不需要使用显式事务:
DELETE TOP(1)FROM BlockedNumber OUTPUT DELETED.
将完成此任务。还有一个额外的好处是,它修复了不完整的语义,这意味着您的
SELECT
DELETE
可能引用不同的行,因为没有明确的排序或筛选。
Create procedure [dbo].[Select_BlockedNubmer]
@id varchar(max)
as
begin
    begin transaction
    set rowcount 1
    select * from BlockedNumber
    delete from BlockedNumber
    set rowcount 0
    commit transaction
end