0

I'm sure this has been asked millions of times before but I'm banging my head against a brick wall at the moment. First I will give you an overview of my goals:

I am creating a media conversion application using C# in Visual Studio 2010. I have successfully managed to convert from MP3, WAV, WMA and OGG into the AIFF file format using NAudio, however that time has come where I need to use BackgroundWorker to convert the files as the program locks up during the conversion process, and I want the progress text to be updated while they are converting. The selected media files will be in a ListView box and I use a foreach loop to run through the ListView and then convert the files individually.

The problem I am facing is accessing the ListView from a seperate thread. The error I get in debugging is:

Cross-thread operation not valid: Control 'listView1' accessed from a thread other than the thread it was created on

Here is my code to convert the files:

        foreach (ListViewItem item in listView1.Items)
        {
            worker.ReportProgress((i * listView1.Items.Count));
            if(item.Text.EndsWith(".mp3"))
            {
                using (Mp3FileReader mp3 = new Mp3FileReader(item.Text))
                {
                    using (WaveStream pcm = WaveFormatConversionStream.CreatePcmStream(mp3))
                    {
                        AiffFileWriter.CreateAiffFile(item.SubItems[2].Text, pcm);
                    }
                }
                string[] saLvwItem = new string[3];
                saLvwItem[0] = item.SubItems[2].Text;
                saLvwItem[1] = "Conversion completed";
                ListViewItem lvi = new ListViewItem(saLvwItem);
                listView2.Items.Add(lvi);

            } 
            else
            {
                if (item.Text.EndsWith(".wav"))
                {
                    using (WaveFileReader wav = new WaveFileReader(item.Text))
                    {
                        using (WaveStream pcm = WaveFormatConversionStream.CreatePcmStream(wav))
                        {
                            AiffFileWriter.CreateAiffFile(item.SubItems[2].Text, pcm);
                        }
                    }
                    string[] saLvwItem = new string[3];
                    saLvwItem[0] = item.SubItems[2].Text;
                    saLvwItem[1] = "Conversion completed";
                    ListViewItem lvi = new ListViewItem(saLvwItem);
                    listView2.Items.Add(lvi);
                }
                else
                {
                    if (item.Text.EndsWith(".wma"))
                    {
                        using (WMAFileReader wma = new WMAFileReader(item.Text))
                        {
                            using (WaveStream pcm = WaveFormatConversionStream.CreatePcmStream(wma))
                            {
                                AiffFileWriter.CreateAiffFile(item.SubItems[2].Text, pcm);
                            }
                        }
                        string[] saLvwItem = new string[3];

                        saLvwItem[0] = item.SubItems[2].Text;
                        saLvwItem[1] = "Conversion completed";
                        ListViewItem lvi = new ListViewItem(saLvwItem);
                        listView2.Items.Add(lvi);
                    }
                    else
                    {
                        string[] saLvwItem = new string[3];
                        saLvwItem[0] = item.SubItems[2].Text;
                        saLvwItem[1] = "Not converted. Unsupported format";
                        ListViewItem lvi = new ListViewItem(saLvwItem);
                        listView2.Items.Add(lvi);
                    }
                }
            }
        }

Which needs to be called from the backgroundWorker1_DoWork event.

Could anyone tell me how I can get this working?

Thanks in advance...

Ricky
  • 2,323
  • 6
  • 22
  • 22
user3733885
  • 381
  • 2
  • 16
  • Yes it has been asks many, many times. Please next time first paste the error message in the search box – Emond Jun 12 '14 at 11:58
  • http://www.dreamincode.net/forums/topic/112547-using-the-backgroundworker-in-c%23/ ----- check out this link for practical example. –  Jun 12 '14 at 12:21

1 Answers1

0

If you want to call form controls in different thread then all you need to do is this:

this.Invoke(new MethodInvoker(delegate { ListView1.Enable = true; }));

Look at ListView1.Enable = true; in the above line. Replace it with what ever you trying to do with the ListView1. Another example:

this.Invoke(new MethodInvoker(delegate { ListView1.Visible = true; }));

ListView listview2 = null; 
this.Invoke(new MethodInvoker(delegate { listview2 = listview1; }));
foreach (ListViewItem item in listView2.Items)
{
    worker.ReportProgress((i * listView2.Items.Count));
    .
    .
    .//Replace listview1 with listview2 in the remaining code
    .//your rest of the code

Hope that helps.

Ricky
  • 2,323
  • 6
  • 22
  • 22
  • Do you have a full example, I am learning C# at the moment but not perfect with it yet. Thanks for the reply :) – user3733885 Jun 12 '14 at 11:59
  • In which line you are getting the error in the above code? – Ricky Jun 12 '14 at 12:00
  • In the backgroundWorker1_DoWork event as soon as I call foreach (ListViewItem item in listView1.Items) it throws the error – user3733885 Jun 12 '14 at 12:02
  • `ListView listview2; this.Invoke(new MethodInvoker(delegate { listview2 = listview1; }));` Then replace `listview1` in `foreach` loop with `listview2` – Ricky Jun 12 '14 at 12:11
  • I tried foreach (ListViewItem item in listview2.Items) and get "Use of unassigned local variable 'listview2'". Not sure whats happening. Thanks again for the help though its much appreciated. – user3733885 Jun 12 '14 at 12:18
  • assign it null first. – Ricky Jun 12 '14 at 12:20
  • How would I go about that? Would it simply be listview2 = null; after the invoke? – user3733885 Jun 12 '14 at 12:26
  • See my answer. You need to do it when declaring. – Ricky Jun 12 '14 at 12:31
  • @user3733885 have you checked this link http://www.dreamincode.net/forums/topic/112547-using-the-backgroundworker-in-c%23/ ? –  Jun 12 '14 at 13:02