1

我有一个带有一些下载链接的“链接”表。

我的 .NET 应用程序读取此表、获取链接、创建 Web 客户端并下载相关文件。我想创建几个线程来执行此操作,但每个线程都应该读取不同的记录,否则两个线程会尝试下载同一个文件。怎么能做到这一点?

我已经尝试过了,但它不起作用:

    public static Boolean Get_NextProcessingVideo(ref Int32 idVideo, ref String youtubeId, ref String title)
    {
        Boolean result = false;

        using (NpgsqlConnection conn = new NpgsqlConnection(ConfigurationDB.GetInstance().ConnectionString))
        {
            conn.Open();
            NpgsqlTransaction transaction = conn.BeginTransaction();

            String query = "BEGIN WORK; LOCK TABLE links IN ACCESS EXCLUSIVE MODE; SELECT v.idlink,  v.title " +
                " FROM video v  WHERE v.schedulingflag IS FALSE AND v.errorflag IS FALSE ORDER BY v.idvideo  LIMIT 1; " + 
                " COMMIT WORK;";
            NpgsqlCommand cmd = new NpgsqlCommand(query, conn, transaction);

            NpgsqlDataReader dr = cmd.ExecuteReader();

            if (dr.HasRows)
            {
                dr.Read();


                idVideo = Convert.ToInt32(dr["idvideo"]);
                title = dr["title"].ToString();

                Validate_Scheduling(idVideo); // 
                result = true;
            }

            transaction.Commit();
            conn.Close();

        }
        return result;
    }
4

1 回答 1

1

您在这里有几个选择。正如您所指出的,您不想做的一件事是锁定桌子。

  1. 咨询锁。优点是这些是额外的事务。缺点是它们不会在事务中关闭,必须专门关闭,并且泄漏最终会导致问题(本质上是后端的共享内存泄漏)。一般来说,我不喜欢这样的额外事务锁,虽然在数据库会话结束时清除了咨询锁,但仍然可能存在陈旧锁的问题。

  2. 您可以让一个专用线程首先拉取待处理的文件,然后将特定的检索委托给子线程。就数据库往返和操作简单性而言,这可能是最好的方法。我希望这将在任何解决方案中表现最好。

  3. 您可以在可以处理异常处理的存储过程中 SELECT FOR UPDATE NOWAIT。有关示例,请参阅在 Postgresql 中选择未锁定的行。

于 2013-02-17T01:44:41.513 回答