Использование Blocking Collection для доступа к базе данных и загрузки изображений в C#

Я работаю над программой, в которой есть две кнопки на форме. Первый выполняет функцию доступа к базе данных, а другой загружает изображение из базы данных и сохраняет его вместе с 3 копиями изображения (Thumbnail, zoom, small).

Код для доступа к базе данных

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<>, Часть производителя выполняет функцию загрузки исходного изображения и его сохранения, в то время как часть потребителя выполняет функцию доступа к очереди производителя, чтобы получить изображение одно за другим, а затем генерировать копии.

Код, реализующий BlockingCollection

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, загрузить новое изображение и сгенерировать его копии.

2 ответа

Решение

Для будущих читателей, которые могут столкнуться с подобной проблемой, вот как модифицированный код для достижения решения. Надеюсь, поможет.

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);

                    }

                   }
        }

Вероятно, это не ваша проблема, но я бы посоветовал вам использовать следующий код:

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

а не просто конкатенация. Таким образом вы избежите многих ошибок.

Другие вопросы по тегам