What im doing is creating a dll that parses xml documents located on the interwebs. The issue that im having is that the application that will use it freezes while the documents are retreived and parsed. So, im under the impression that i will need to utilize threading of some sort. My question is, is it possible, from main thread, to pass args to a backgroundworker, which will pass them to a method, that will use it to return a string, which will then be returned to the main thread?

Or, is there a better/simpler way to go about this?

And, would anyone be willing to offer an example?

Thx in adv

Recommended Answers

All 4 Replies

Oh there is indeed. I just recently learned this myself.

(Please make sure to read this all the way through, it might clear itself up at the end)

First of all, we'll assume you at least know a little about backgroundWorkers (if not I can elaborate more). First of all let's start with your function that will start the backgroundWorker.

To pass in multiple arguments to a backgroundWorker first we'll need to create a list.

List<object> arguments = new List<object>(); //adds objects to the list, to pass into the background worker
arguments.Add("arguments go here");
    //just like a list, you can add multiple arguments

if (backgroundWorker1.IsBusy != true) //if the backgroundWorker isn't running
{
    backgroundWorker1.RunWorkerAsync(arguments); //Start the asynchronous operation.
}

Alright now that the backgroundWorker started, let's head over to the DoWork. The DoWork is where all your work will be done (reading in or what not). In this function we'll extract the values you wanted to work with

private void backgroundWorker1_DoWork (object sender, DoWorkEventArgs e)
{
    List<object> argumentList = e.Argument as List<object>; //acquires the passed in arguments

    string argument1 = (string) argumentList [0];
        //you can extract multiple arguments passed in, just like an array, 
        //retrieving them the order you added them to the list. Also don't forget
        //to typecast

    /* here do what you want to do */
}

Now to pass back a value, you can use Delegates (which are really fun and nice to know). These are the equivalent of a pointer in other languages (like C) you might say.

To do this we need to add a piece of code right below the namespace

namespace ScoreTableDetector2_1v9
{
    public delegate void Return_CallBack(string returnedInfo);
        //you can call it what you want, doesn't have to be "Return_CallBack"
        //Also you can add multiple values to pass back (just like a function)

    //NOTE: this is to come before your "public class Form1" line (or however
    //title it).
}

Once there, we'll be going back to the where we made the argument list (and then onto the DoWork) and we'll be adding the following to the list

List<object> arguments = new List<object>(); 
arguments.Add("arguments go here");
arguments.Add(new Return_CallBack(myFunction));
    //"myFunction" is a function that will be called back to. It's parameters need
    //to match that of the Return_CallBack we did earlier on

if (backgroundWorker1.IsBusy != true)
{
    backgroundWorker1.RunWorkerAsync(arguments);
}

Then, into the DoWork

private void backgroundWorker1_DoWork (object sender, DoWorkEventArgs e)
{
    List<object> argumentList = e.Argument as List<object>; 

    string argument1 = (string) argumentList [0];
    Return_CallBack callBackTo = (Return_CallBack) argumentList[1];

    /* here do what you want to do */

    //NOTE: what we are adding below. 

    if (callBackTo != null)
    {
        callBackTo("data to pass back");
    }

    //This piece of code here, with the if statement, is how we pass back the data
    //we want. Or more specifically call a function with the data we want, going
    //back to the main thread.
}

So as you can see above, that part I added onto the end, is how you passback data.

Okay so I realized this seems all over the place, so I have added a code below that shows all the stuff we talked about incorporated into code you might see creating a form (this should help clear up the confusion my mind has caused you)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace MyProgram
{
    public delegate void Return_CallBack(string returnedInfo);

    public partial class Form1 : Form
    {
        public Form1 ()
        {
            InitializeComponent();

            backgroundWorker1.WorkerReportsProgress = true; //I never fully know what these are for, but I always set them to true (lol)
            backgroundWorker1.WorkerSupportsCancellation = true; 
        }

        private void button1_Click (object sender, EventArgs e) //Button1 is clicked
        {
            /* Let's say we need to get a file name for this example */

            if (openFileDialog1.ShowDialog() == DialogResult.OK) //selected a file to open
            {
                List<object> arguments = new List<object>();
                arguments.Add(openFileDialog1.FileName);
                arguments.Add(new Return_CallBack(callBack_Function));

                if (backgroundWorker1.IsBusy != true)
                {
                    backgroundWorker1.RunWorkerAsync(arguments);
                }
            }
        }

        private void backgroundWorker1_DoWork (object sender, DoWorkEventArgs e)
        {
            string fileName = (string) argumentList [0];
            Return_CallBack callBackTo = (Return_CallBack) argumentList[1];

            string dataToPassBack = "";

            /* Do your work here */

            if (callBackTo != null)
            {
                callBackTo(dataToPassBack);
            }
        }

        private void callBack_Function (string returnedData) //the function that the delegate will call back to
        {
            //note here the parameter's actual name doesn't need to match above

            MessageBox.Show(returnedData);
        }
    }
}

Did this all make sense? My mind is flying 20 directions so to me it's clear.

This does make sense, but I'm unsure how to fit this to what is needed

public static string func()
{
    BackgroundWorker.RunWorkerAsync(args);
    return ???;
}

is there any way to get a return for this?

Yep you bet there is.

Let's go back to that delegate I told you about the code (where we used the following code)

if (callBackTo != null)
{
    callBackTo(dataToPassBack);
}

That right there is your "return". With threads it's hard to just just do a return because of how they work (I can't remember the exact reason at the moment). So what you are doing with the code above is calling a function from some other part in the program (heck you can be in another class) and passing the data back.

Of course don't forget all the other work you need to do to set up the delegate. Take another look at the code I posted in my original post.

If you are still a little puzzled let me know

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.