Использование 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));
а не просто конкатенация. Таким образом вы избежите многих ошибок.