c# Selenium和Chrome中的队列问题

cs7cruho  于 2023-03-06  发布在  Go
关注(0)|答案(1)|浏览(174)

我正在尝试写一个软件来捕获直接下载链接使用 selenium 和 chrome 。它有客户端发送文件下载链接请求到服务器通过微软。net远程技术。然后,文件下载链接将被添加到队列上的服务器。通过使用while(true)循环,我保持服务器活着,以听取请求发送的客户端。
1.点击“启动服务器”按钮(DownloadShare 2()函数),程序将创建一个新线程,While循环将运行,并侦听请求,我第一次按下“添加到队列”按钮(addQueue()函数)时,效果很好,文件下载链接添加到队列中,请求传递到chrome驱动程序,它开始下载文件。
1.第二次,是的仍然工作正常。
1.但是,在几次无法计数之后(可能是2次,也可能是4次或5次),它就不会像第一次那样工作了,“queue”仍然会计算调用addQueue()函数时添加的元素数;但是在while循环中,这个元素不能被计数,A点的计数可能是3,但是B点的计数总是0。
我的队列2.计数;//======〉A点
我的队列2.计数;//======〉B点
1.然而,如果我再次按下“启动服务器”按钮,它就会像第一次一样运行。
在代码部分,我删除了几行不必要或不太可能出错的代码,所以如果你看到类似下面的代码,请不要太惊讶。
字符串会话链接1 =我的队列2.出队().到字符串().修剪();
字符串链接共享1 =会话链接1;
我不知道为什么会这样。我试过改变很多东西,但仍然是同样的错误。如果你需要这个项目的所有源代码,给我留言。非常感谢。

public string startServer()
        {
            Console.WriteLine("Point: 7");
            try
            {
                Thread startServer = new Thread(DownloadShare2);
                startServer.Start();
                Console.WriteLine("Point: 8");
                return "Start server ok";
            }
            catch (Exception ex)
            {
                return "Start server faile";
            }
        }

        Queue MyQueue2 = new Queue();
        int countMyQueue2 = 0;

        public string addQueue(string Link1)
        {
            try
            {
                Console.WriteLine("Point: 9");
                string sessionLink1 = Link1;
                MyQueue2.Enqueue(sessionLink1);
                Console.WriteLine("Count Queue 1: " + MyQueue2.Count);
                countMyQueue2 = MyQueue2.Count; **// =======> Point A**
                Console.WriteLine("Count Queue 1: CountMyQueue2: " + countMyQueue2);
                Thread.Sleep(1000);
                return "\r\nAdded " + MyQueue2.Count + " --------- " + countMyQueue2;
            }
            catch (Exception ex)
            {
                Console.WriteLine("Point: 10");
                return "Add faile";
            }
        }

        public void DownloadShare2()
        {
            Console.WriteLine("Point: 11");
            Console.WriteLine("Server Started");
            Console.WriteLine("Point: 14");

            if (chromeCount == 0)
            {
                createChromeDrive();
                chromeCount = 1;
                Console.WriteLine("Point: 14");
            }

            while (true)
            {
                /*
                1. Click the "Start server" button, the program will create a new thread, the While loop will run, and listen for requests.
                The first time I pressed the "Add to Queue" button, it worked great. 
                The file download link is added to the queue, and the request is passed to the chrome driver, which starts downloading the file.
                2. The second time, yes still works fine.
                3. But then, after a few times without being able to count (maybe 2 times, maybe 4 or 5 times), it won't work as well as the first time.
                The "queue" still counts the number of elements added when the addQueue() function is called;
                But in the while loop, the element cannot be counted. Always MyQueue2.Count = 0;
                .
                4. However if I then press the "Start server" button again, it runs just like the first time.
                */
                Console.WriteLine("Count Queue 2: " + MyQueue2.Count);  **// =======> Point B**
                Console.WriteLine("Count Queue 2: CountMyQueue2: " + countMyQueue2);
                if (countMyQueue2 < 1)
                {
                    //keep the server alive to listen to requests sent by the client.
                    Console.WriteLine("Point: 16 ");
                    Thread.Sleep(1000);
                }
                else if (countMyQueue2 > 0)
                {
                    IJavaScriptExecutor jse2 = (IJavaScriptExecutor)driver;
                    driver.Navigate().GoToUrl("chrome://downloads/");
                    Thread.Sleep(500);
                    Console.WriteLine("Point: 17");
                    Actions keyAction = new Actions(driver);
                    keyAction.KeyDown(Keys.Alt).KeyDown("c").KeyUp("c").KeyUp(Keys.Alt).Build().Perform();
                    Thread.Sleep(1000);
                    Console.WriteLine("Point: 18");

                    Console.WriteLine("Point: 19");

                    string sessionLink1 = MyQueue2.Dequeue().ToString().Trim();
                    countMyQueue2 = countMyQueue2 - 1;

                    Console.WriteLine("Count Queue 3: CountMyQueue2: " + countMyQueue2);
                    Console.WriteLine("Count Queue 3 (Dequeue): " + MyQueue2.Count);

                    Console.WriteLine(sessionLink1);
                    linkShare1 = sessionLink1;

                    Console.WriteLine("Link file: " + linkShare1);
                    try
                    {
                        Console.WriteLine("Point: 20");
                        //string linkDownload = "";
                        string tmpSizeAndNamefile = getSizeOfFile(linkShare1);
                        //get file size
                        double sizeOfFile = double.Parse(tmpSizeAndNamefile.Substring(0, tmpSizeAndNamefile.IndexOf("!")));
                        Console.WriteLine("sizeOfFile: " + sizeOfFile);
                        //get file name
                        fileName1 = tmpSizeAndNamefile.Substring(tmpSizeAndNamefile.IndexOf("!") + 1);
                        Console.WriteLine("fileName1: " + fileName1);

                        Console.WriteLine("Point: 21");

                        try
                        {
                            driver.Navigate().GoToUrl(linkShare1);
                            Thread.Sleep(500);
                            {
                                driver.Navigate().GoToUrl("chrome://downloads/");
                                Thread.Sleep(2000);
                                var linkDownloadX = jse2.ExecuteScript("return document.querySelector(\"body>downloads-manager\").shadowRoot.querySelector(\"#frb0\").shadowRoot.querySelector(\"#url\").getAttribute(\"href\")");

                                //get Download link from Chrome download page.
                                linkDownload2 = linkDownloadX.ToString();
                                Console.WriteLine("Point: 29");

                                Thread.Sleep(500);
                                Console.WriteLine("Point: 31");

                                //Clear all Download history
                                keyAction.KeyDown(Keys.Alt).KeyDown("c").KeyUp("c").KeyUp(Keys.Alt).Build().Perform();
                                Thread.Sleep(1000);
                                Console.WriteLine("Point: 32");
                            }
                        }
                        catch (System.NullReferenceException nullex)
                        {
                            Console.WriteLine("Count Queue 6: CountMyQueue2: " + countMyQueue2);
                            Console.WriteLine("Point: 33");
                        }
                        catch (OpenQA.Selenium.JavaScriptException jsex)
                        {
                            Console.WriteLine("Count Queue 7: CountMyQueue2: " + countMyQueue2);
                            Console.WriteLine("Point: 35");
                        }

                        //write log to TXT file
                        WriteLog(DateTime.Now.ToString("yyyyMMddHHmmss") + "~" + sizeOfFile + "!" + linkShare1 + "@3" + linkDownload2.ToString() + "\r\n");
                        WriteLink(DateTime.Now.ToString("yyyyMMddHHmmss") + "~" + sizeOfFile + "!" + linkShare1 + "@3" + linkDownload2.ToString());

                        Console.WriteLine("Point: 37");
                        Thread.Sleep(500);
                        Console.WriteLine("Point: 38");

                        //Create new thread Download file
                        Thread tDownload = new Thread(DownloadFunc);
                        tDownload.Start();
                    }
                    catch (NullReferenceException nullex)
                    {
                        MessageBox.Show("NullReferenceException");
                        Console.WriteLine("Point: 39");
                    }
                    catch (Exception dex)
                    {
                        Console.WriteLine("Point: 40");
                        Console.WriteLine("Error6");
                    }
                    Console.WriteLine("Point: 47");
                }
            }
        }
3gtaxfhh

3gtaxfhh1#

从多个线程访问队列似乎可能存在并发问题。在多线程环境中,操作系统调度线程执行的顺序是不确定的,并且它可以从一个执行到下一个执行而改变。因此,当一个线程可能正在处理队列中的一个项目时,另一个线程可以从队列中抓取不同的项目并在第一个线程完成处理其当前项目之前处理它。
以下是来自docs的建议:
此类型的公共静态(在Visual Basic中为Shared)成员是线程安全的。不能保证任何示例成员都是线程安全的。
Queue<T>可以同时支持多个读取器,只要集合没有被修改。即使如此,枚举集合本质上不是线程安全的过程。有关线程安全队列,请参见ConcurrentQueue<T>
ConcurrentQueue<T>确保对队列的访问是同步的,并且对于多个线程同时访问是安全的。

ConcurrentQueue<string> myQueue = new ConcurrentQueue<string>();

// Enqueue an item
string item = "item1";
myQueue.Enqueue(item);

// Dequeue an item
if (myQueue.TryDequeue(out string dequeuedItem))
{
    // Do something with the dequeued item
}

您可以将现有的Queue替换为ConcurrentQueue<T>,看看它是否能解决问题。
不使用ConcurrentQueue<T>也可以解决此问题。可以使用lock语句来同步对队列的访问。它用于在访问队列之前获取对象上的排它锁。这确保了一次只有一个线程可以访问队列。

private static Queue<int> queue = new Queue<int>();
private static object queueLock = new object();

public static void Producer()
{
    for (int i = 0; i < 10; i++)
    {
        lock (queueLock)
        {
            queue.Enqueue(i);
            Console.WriteLine($"Producer enqueued {i}.");
        }
        Thread.Sleep(100);
    }
}

public static void Consumer()
{
    while (true)
    {
        lock (queueLock)
        {
            if (queue.Count > 0)
            {
                int item = queue.Dequeue();
                Console.WriteLine($"Consumer dequeued {item}.");
            }
        }
        Thread.Sleep(100);
    }
}

相关问题