Need some mojo with using BackGround worker.

Crap, why is MSDN information so vague?

Page 1 of 1

10 Replies - 2752 Views - Last Post: 29 May 2009 - 08:58 AM Rate Topic: -----

#1 papuccino1  Icon User is offline

  • His name was Robert Paulson.
  • member icon

Reputation: 63
  • View blog
  • Posts: 1,121
  • Joined: 02-March 08

Need some mojo with using BackGround worker.

Post icon  Posted 28 May 2009 - 06:59 AM

Hey there folks.

I have my program that searches IMDB for movies. Ok.

WebClient.DownloadData(TheURL); downloads the websites source code and this usually takes around 3 seconds on a good connection (more, if your internet sucks). During this download, the entire UI freezes and make me look like a bad, bad programmer. A friend told me to look into BackGround worker class.

He also said that when you create a thread you can't have that particular method recieve any parameters. Is this true? If so, I have already modified my method to have no parameters.


Could I trouble any of you to make a little example using the background worker class? Pretty please with a Victorias Secret model on top?

Grazie.

Edit: So you guys don't think I'm some sort of lazy bum, here's the method I need to have "working" in the background. It's located in the IMDBMovie.cs class, outside of Form1 class.

public string[] IMDBMovieInformation(string Query)
        {            
            string[] MovieInformation = new string[5];

            TheDataBuffer = TheWebClient.DownloadData(IMDBMovieSearch(Query));
            TheWebSource = Encoding.ASCII.GetString(TheDataBuffer);

            MovieInformation[0] = FindTitle(TheWebSource);
            MovieInformation[1] = FindPoster(TheWebSource);
            MovieInformation[2] = FindPlot(TheWebSource);
            MovieInformation[3] = FindGenre(TheWebSource);
            MovieInformation[4] = FindYear(TheWebSource);

            return MovieInformation;
        }

This post has been edited by papuccino1: 28 May 2009 - 07:05 AM


Is This A Good Question/Topic? 0
  • +

Replies To: Need some mojo with using BackGround worker.

#2 eclipsed4utoo  Icon User is offline

  • Not Your Ordinary Programmer
  • member icon

Reputation: 1524
  • View blog
  • Posts: 5,960
  • Joined: 21-March 08

Re: Need some mojo with using BackGround worker.

Posted 28 May 2009 - 07:37 AM

here is a nice tutorial on using the BackGroundWorker with parameters...

http://dotnetperls.c...troduction.aspx
Was This Post Helpful? 0
  • +
  • -

#3 papuccino1  Icon User is offline

  • His name was Robert Paulson.
  • member icon

Reputation: 63
  • View blog
  • Posts: 1,121
  • Joined: 02-March 08

Re: Need some mojo with using BackGround worker.

Posted 28 May 2009 - 07:47 AM

I've seen that tutorial but it's very dificult for me to wrap my head around it. Basically what I want is for my single method to execute in the background. Nothing more, nothing less.

Please help Eclipsed!!!
Was This Post Helpful? 0
  • +
  • -

#4 lesPaul456  Icon User is offline

  • D.I.C Addict
  • member icon

Reputation: 173
  • View blog
  • Posts: 729
  • Joined: 16-April 09

Re: Need some mojo with using BackGround worker.

Posted 28 May 2009 - 08:09 AM

View Postpapuccino1, on 28 May, 2009 - 08:47 AM, said:

I've seen that tutorial but it's very dificult for me to wrap my head around it. Basically what I want is for my single method to execute in the background. Nothing more, nothing less.

Please help Eclipsed!!!


Hello,

I think you can do this by calling the background workers "RunWorkerAsync()" method, and passing your argument. Then, store the result from the method in e.Result:

// Call background worker's "RunWorkerAsync()" method
backgroundWorker1.RunWorkerAsync("Query");

// The background worker's "DoWork" event handler
pribvtae void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
	 // Call the method and store the result
	 e.Result = IMDBMovieInformation(e.Argument as string);
}

// The background workers "RunWorkerCompleted" event handler
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
	 // Do whatever you want with e.Result.
}



Replace "Query" with whatever you want the IMDBMoveInformation() parameter to be.

Hope this helps!
Was This Post Helpful? 0
  • +
  • -

#5 T3hC13h  Icon User is offline

  • D.I.C Regular

Reputation: 65
  • View blog
  • Posts: 337
  • Joined: 05-February 08

Re: Need some mojo with using BackGround worker.

Posted 28 May 2009 - 08:28 AM

Quote

He also said that when you create a thread you can't have that particular method recieve any parameters. Is this true? If so, I have already modified my method to have no parameters.

He is incorrect.

Checkout this awesome tutorial on threading in C# and .Net.
Was This Post Helpful? 0
  • +
  • -

#6 masteryee  Icon User is offline

  • D.I.C Regular

Reputation: 40
  • View blog
  • Posts: 271
  • Joined: 16-May 09

Re: Need some mojo with using BackGround worker.

Posted 28 May 2009 - 08:44 AM

Unless your FindTitle, FindPoster, and other Find methods are intensive, then you don't really need a backgroundworker. Just use the asynchronous version of DownloadData (DownloadDataAsync). Here's a simple form with a button and textbox, using the asynchronous download method that won't freeze your GUI:

    public partial class Form1 : Form
    {
        WebClient TheWebClient;
        public Form1()
        {
            InitializeComponent();
            TheWebClient = new WebClient();
            TheWebClient.DownloadDataCompleted += new DownloadDataCompletedEventHandler(TheWebClient_DownloadDataCompleted);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Uri dreamInCode = new Uri("http://www.dreamincode.net/forums/showtopic107418.htm");

            // DownloadDataAsync accepts an object as an optional 2nd parameter
            TheWebClient.DownloadDataAsync(dreamInCode, 12346789);
            
        }

        private void TheWebClient_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
        {
            // extract the byte[] result from the download
            string TheWebSource = Encoding.ASCII.GetString(e.Result);
            textBox1.Text = TheWebSource;

            // if we passed in a second parameter to DownloadDataAsync...
            int userData = (int)e.UserState;
            MessageBox.Show(userData.ToString());
        }
    }


Was This Post Helpful? 0
  • +
  • -

#7 papuccino1  Icon User is offline

  • His name was Robert Paulson.
  • member icon

Reputation: 63
  • View blog
  • Posts: 1,121
  • Joined: 02-March 08

Re: Need some mojo with using BackGround worker.

Posted 28 May 2009 - 08:51 AM

View Postmasteryee, on 28 May, 2009 - 07:44 AM, said:

Unless your FindTitle, FindPoster, and other Find methods are intensive, then you don't really need a backgroundworker. Just use the asynchronous version of DownloadData (DownloadDataAsync). Here's a simple form with a button and textbox, using the asynchronous download method that won't freeze your GUI:

    public partial class Form1 : Form
    {
        WebClient TheWebClient;
        public Form1()
        {
            InitializeComponent();
            TheWebClient = new WebClient();
            TheWebClient.DownloadDataCompleted += new DownloadDataCompletedEventHandler(TheWebClient_DownloadDataCompleted);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Uri dreamInCode = new Uri("http://www.dreamincode.net/forums/showtopic107418.htm");

            // DownloadDataAsync accepts an object as an optional 2nd parameter
            TheWebClient.DownloadDataAsync(dreamInCode, 12346789);
            
        }

        private void TheWebClient_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
        {
            // extract the byte[] result from the download
            string TheWebSource = Encoding.ASCII.GetString(e.Result);
            textBox1.Text = TheWebSource;

            // if we passed in a second parameter to DownloadDataAsync...
            int userData = (int)e.UserState;
            MessageBox.Show(userData.ToString());
        }
    }




Ooh la-lá. Now this looks like something that would fit the bill with my current project. I'll have to check this out, ASAP.

Thank you for all the information guys, I'll give all of them a try and get back to you guys. :D
Was This Post Helpful? 0
  • +
  • -

#8 papuccino1  Icon User is offline

  • His name was Robert Paulson.
  • member icon

Reputation: 63
  • View blog
  • Posts: 1,121
  • Joined: 02-March 08

Re: Need some mojo with using BackGround worker.

Posted 28 May 2009 - 08:13 PM

After tinkering a bit I found this problem, I need some help here:

public string[] IMDBMovieInformation(string Query)
        {            
            string[] MovieInformation = new string[5];
            Uri X = new Uri(IMDBMovieSearch(Query));

            TheDataBuffer = TheWebClient.DownloadDataAsync(X); //(IMDBMovieSearch(Query)); //Error! Cannot convert Void to Int[]. DownloadDataAsync returns a void?
            TheWebSource = Encoding.ASCII.GetString(TheDataBuffer);

            MovieInformation[0] = FindTitle(TheWebSource);
            MovieInformation[1] = FindPoster(TheWebSource);
            MovieInformation[2] = FindPlot(TheWebSource);
            MovieInformation[3] = FindGenre(TheWebSource);
            MovieInformation[4] = FindYear(TheWebSource);

            return MovieInformation;
        }


My downloaddataasync part is return a void, why? The IDE description says it return an int[] so it should save properly to the databuffer which is of type int[] as well.

Edit: Even Microsoft says it:
http://msdn.microsof...190(VS.80).aspx

Downloads the specified resource as a Byte array. This method does not block the calling thread.


Thanks for the help. :D

This post has been edited by papuccino1: 28 May 2009 - 08:31 PM

Was This Post Helpful? 0
  • +
  • -

#9 MasterDisaster  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 29-December 07

Re: Need some mojo with using BackGround worker.

Posted 29 May 2009 - 03:23 AM

Here is a example how to pass multiple parameters to a BackgroundWorker component

public partial class Form1 : Form
{
	TheWebClient WebClient;
       	bool flag = true;
        public Result()
        {
            InitializeComponent();
            WebClient = new TheWebClient();
        }
        private void button1_Click(object sender, EventArgs e)
        {
            object[] param = new object[5];
            param[0] = (object)textbox1.Text;
            param[1] = (object)textbox2.Text;
            param[2] = (object)textbox3.Text;
            param[3] = (object)flag;
            button1.Enabled = false;
            backgroundWorker1.RunWorkerAsync(param);
        }

        private void GetData(object[] arg, BackgroundWorker worker)
        {
            WebClient.DownloadData((string)arg[0], (string)arg[1], (string)arg[2], (bool)arg[3], worker);
        }

        public void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            GetData((object[])e.Argument, worker);        
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            toolStripProgressBar1 = e.ProgressPercentage;
            toolStripStatusLabel1.Text = "Downloading.. " + e.ProgressPercentage + "%";
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            toolStripStatusLabel1.Text = "Operation Complete";
            toolStripProgressBar1.Visible = false;
            button1.Enabled = true;
        }
}



To update the toolstrip progress bar you need to use the worker object in the DownloadData function.

        public void DownloadData(string address, string from, string to, bool flag, BackgroundWorker worker)
        {
            string strURL1 = address;
            if (flag)
            {
              //do something
            }
            double progressMin = 0;
            double progressMax = Convert.ToInt32(to) - Convert.ToInt32(from);
            int percentDone;
            for (i = Int32.Parse(from); i <= Int32.Parse(to); i++)
            {
                percentDone = Convert.ToInt32(progressMin / progressMax * 100);
                progressMin++;
                worker.ReportProgress(percentDone);
                string strURL = strURL1 + i.ToString();
                GetFile(strURL);
            }
        }


Was This Post Helpful? 0
  • +
  • -

#10 eclipsed4utoo  Icon User is offline

  • Not Your Ordinary Programmer
  • member icon

Reputation: 1524
  • View blog
  • Posts: 5,960
  • Joined: 21-March 08

Re: Need some mojo with using BackGround worker.

Posted 29 May 2009 - 03:44 AM

the IDE says it returns a void. and the MSDN says it returns a byte array.

now, a quick google search on how to use the DownloadDataAsync would have showed you what is going on. The DownloadDataAsync method itself doesn't return anything. You have to get the result by using the DownloadDataCompleted event handler....

public string[] IMDBMovieInformation(string Query)
{
	string[] MovieInformation = new string[5];
	Uri X = new Uri(IMDBMovieSearch(Query));

	TheWebClient.DownloadDataCompleted += new DownloadDataCompletedEventHandler(TheWebClient_DownloadDataCompleted);
	TheWebClient.DownloadDataAsync(X);
}

void TheWebClient_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
	byte[] returnedData = e.Result;
	// now your code to process the returned data
}


This post has been edited by eclipsed4utoo: 29 May 2009 - 03:44 AM

Was This Post Helpful? 1
  • +
  • -

#11 masteryee  Icon User is offline

  • D.I.C Regular

Reputation: 40
  • View blog
  • Posts: 271
  • Joined: 16-May 09

Re: Need some mojo with using BackGround worker.

Posted 29 May 2009 - 08:58 AM

Sorry I wasn't clearer earlier, but you really took my example out of context. DownloadDataAsync returns void instantly because this is the nature of asynchronous methods; it actually launches the download in a background thread and allows your main code to continue to run. The WebClient has an event called DownloadDataCompleted, which occurs once the DownloadDataAsync method has completed its download. The DownloadDataCompletedEventArgs argument will contain the byte[] data you're looking for in its Result field. I don't know exactly how your program is supposed to run, but here's one way to implement it based off the code you provided:
    public partial class Form1 : Form
    {
        WebClient TheWebClient;
        string[] MovieInformation;

        public Form1()
        {
            InitializeComponent();
            MovieInformation = new string[5];
            TheWebClient = new WebClient();
            TheWebClient.DownloadDataCompleted += new DownloadDataCompletedEventHandler(TheWebClient_DownloadDataCompleted);
        }
        public void IMDBMovieInformation(string Query)
        {
            Uri imdb = new Uri(IMDBMovieSearch(Query));
            TheWebClient.DownloadDataAsync(imdb);
        }
        private void button1_Click(object sender, EventArgs e)
        {
            IMDBMovieInformation("hello world");
        }

        private void TheWebClient_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
        {

            // extract the byte[] result from the download
            string TheWebSource = Encoding.ASCII.GetString(e.Result);

            MovieInformation[0] = FindTitle(TheWebSource);
            MovieInformation[1] = FindPoster(TheWebSource);
            MovieInformation[2] = FindPlot(TheWebSource);
            MovieInformation[3] = FindGenre(TheWebSource);
            MovieInformation[4] = FindYear(TheWebSource);
        }
    }


If you prefer to avoid using the DownloadDataAsync method, then your best bet really is BackgroundWorker.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1