在 C# 中使用阻止收集进行数据库访问和下载图像

本文关键字:数据库 访问 图像 下载 | 更新日期: 2023-09-27 17:56:03

我正在开发一个程序,其中表单上有两个按钮。第一个执行访问数据库的功能,而另一个从数据库下载图像并将其与3个图像副本(缩略图,缩放,小)一起保存。

访问数据库的代码

using (SqlConnection connection = new SqlConnection(connectionstring))
        {
            connection.Open();
            using (SqlCommand cm = new SqlCommand("query", connection))
            {
                t1.Load(cm.ExecuteReader());
                foreach (DataRow row in t1.Rows)
                {
                    fileNames.Add(row["Filename"].ToString());
                }
            }
         }

访问数据库后,下一个任务是下载图像,生成其三个副本并将所有内容保存在文件夹中。为此,我正在尝试使用BlockingConnection<>.生产者部分执行下载原始图像并保存的功能,而消费者部分执行访问生产者队列以逐个获取图像然后生成副本的功能。

实现阻塞集合的代码

string baseUrl = "http://some path";

        HttpWebRequest request = null;
        using(BlockingCollection<Image> bc= new BlockingCollection<Image>(20))
        {
        using (Task task1 = Task.Factory.StartNew(() =>
        {
            foreach(var fileName in fileNames)
            {
                string url = string.Format(baseUrl, fileName);
                request = (HttpWebRequest)WebRequest.Create(url);
                request.Method = "GET";
                request.ContentType = "application/x-www-form-urlencoded";
                request.CookieContainer = container;
                response = (HttpWebResponse)request.GetResponse();
                Stream stream = response.GetResponseStream();
                img = Image.FromStream(stream);
                bc.Add(img);
                Thread.Sleep(100);
            }
         }))
                    {
                        using (Task task2 = Task.Factory.StartNew(() =>
                            {
                                foreach (var fileName in fileNames)
                                {
                                    foreach (var item in bc.GetConsumingEnumerable())
                                    {
                                     img.Save("C:''some path" + FileName);
                                    //code to generate copies of images
                                    }
                                }
                            }))
                            Task.WaitAll(task1, task2);
                    }
                   }
        }

让我告诉你,当我使用BackgroundWorker测试它时,这段代码工作得很好。我收到错误的部分是尝试将图像保存在 Task1 中的行。

img.Save("C:''some path" + FileName);

它正在抛出此异常

"An unhandled exception of type 'System.Runtime.InteropServices.ExternalException' occurred in System.Drawing.dll
Additional information: A generic error occurred in GDI+."

我想出了为什么它不保存图像。我已经相应地更改了代码。但它没有正确循环。在获取一个映像并生成其多个副本后,它应该返回到第一个 foreach,下载新映像并生成其副本。

在 C# 中使用阻止收集进行数据库访问和下载图像

这可能不是你的问题,但我建议你使用以下代码:

img.Save(System.IO.Path.Combine("C:''some path",FileName));

而不仅仅是串联。 通过这种方式,您可以避免许多错误。

对于可能遇到类似问题的未来读者,以下是修改后的代码如何找到解决方案。希望对您有所帮助。

string baseUrl = "http://some url";
        HttpWebRequest request = null;
        using(BlockingCollection<object> bc= new BlockingCollection<object>(20))
        {
        using (Task task1 = Task.Factory.StartNew(() =>
        {
            using (SqlConnection connection = new SqlConnection("connectionstring"))
            {
            connection.Open();
            using (SqlCommand cm = new SqlCommand("query", connection))
            {
                t1.Load(cm.ExecuteReader());
                foreach (DataRow row in t1.Rows)
                {
                     fileNames.Add(row["Filename"].ToString());
                     bc.Add(row["Filename"]);
                }
                Thread.Sleep(100);
                Console.WriteLine("This is Add part");
            }
            }
            bc.CompleteAdding();
         }))
                    {
                        using (Task task2 = Task.Factory.StartNew(() =>
                            {
                                    foreach (var item in bc.GetConsumingEnumerable())
                                    {
                                    string url = string.Format(baseUrl, item);
                                    request = (HttpWebRequest)WebRequest.Create(url);
                                    request.Method = "GET";
                                    request.ContentType = "application/x-www-form-urlencoded";
                                    request.CookieContainer = container;
                                    response = (HttpWebResponse)request.GetResponse();
                                    Stream stream = response.GetResponseStream();
                                    img = Image.FromStream(stream);
                                    img.Save("C:''some path" + item);
                                    //code to create copies of image.
                                    }
                                    Console.WriteLine("This is Take part");
                            }))
                                    Task.WaitAll(task1,task2);
                    }
                   }
        }