Question

I am working on a program where there are two buttons on the form. First one performs function of accessing the database while other downloads image from database and saves it along with 3 copies of image (Thumbnail, zoom, small).

Code for Accessing Database

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

                }
            }
         }

After accessing database, next task is to download image, generate its three copies and save everything in a folder. For this purpose, I am trying to use BlockingConnection<>. Producer part performs function of downloading original image and saving it while consumer part performs function of accessing producer queue to get image one by one and then generating copies.

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

                    }
                   }
        }

Let me tell you that this code works perfectly fine when I tested it with BackgroundWorker. The part where I am getting error is line that tries to save the image in Task1.

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

It is throwing this exception

"An unhandled exception of type 'System.Runtime.InteropServices.ExternalException' occurred in System.Drawing.dll

Additional information: A generic error occurred in GDI+."

I figured out why it was not saving images. I have changed code accordingly. But it is not looping properly. After getting one image and generating its multiple copies, it should go back to first foreach, download new image and generate its copies.

Was it helpful?

Solution 2

For future readers who may come across similar problem, here is how modified code to reach to solution. Hope it helps.

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

                    }

                   }
        }

OTHER TIPS

This is probably not your problem but I would suggest you use the following code:

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

and not just concatenation. You avoid many bugs this way.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top