views:

91

answers:

3

Hi,

I have written a code to save the image which is generated by the application. The size of image is around 32-35 MB. While saving the image to a bmb file, it is taking long time around 3-5 secs. For the purpose, I have used background worker but when running background worker, it shows an error like..."cant access the object as it is created on different thread".

Following is the code:

 private void btnSaveDesign_Click(object sender, RoutedEventArgs e)
    {
        Microsoft.Win32.SaveFileDialog sfd = new Microsoft.Win32.SaveFileDialog();
        sfd.Title = "Save design as...";
        sfd.Filter = "BMP|*.bmp";
        if (sfd.ShowDialog() == true)
        {
            ww = new winWait();
            ww.Show();
            System.ComponentModel.BackgroundWorker bw = new System.ComponentModel.BackgroundWorker();
            bw.DoWork += new System.ComponentModel.DoWorkEventHandler(bw_DoWork);
            bw.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
            fName = sfd.FileName;
            cache = new CachedBitmap((BitmapSource)imgOut.Source, BitmapCreateOptions.None, BitmapCacheOption.OnLoad);

            bw.RunWorkerAsync();


        }  
    }

    void bw_RunWorkerCompleted(object sender, System.ComponentModel.RunWorkerCompletedEventArgs e)
    {
        ww.Close();
    }

    void bw_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
    {
        BmpBitmapEncoder encoder = new BmpBitmapEncoder();
        encoder.Frames.Add(BitmapFrame.Create(cache)); //here... it says cant access...
        using (FileStream file = File.OpenWrite(fName))
        {
            encoder.Save(file);
        }
    }

I have declared "cache" as a global object. (The similar trick was worked when I was programming in WinForms with Vb.Net)

ww is the wait window that I want to be displayed while the precess is being executed.

Any idea how to do this? Is there any other simple method for multi threading in Wpf??

Thanks

A: 

I think you have to pass cache as a parameter to the new thread:

bw.RunWorkerAsync(cache);

and get it from the DoWork method:

var cache=(CacheType) e.Argument;
Carles
I tried... but it is showing the same message "The calling thread cannot access this object because a different thread owns it."
Vinod Maurya
The only possible way of passing an object from UI thread to non UI is to pass it by value rather than by reference, but in your case that is not an option, as the object is too big.
Vitalij
+3  A: 

When WPF objects are created they are assigned to a Dispatcher object. This disallows any threads other than the creating thread to access the object. This can be circumvented by freezing the object by calling the freeze method. You would need to call Freeze on your bitmapsource object. Once you have frozen your object it becomes uneditable

mattythomas2000
thanks... it worked!
Vinod Maurya
+3  A: 

ur probelm is because you are accessing a object which is not created by background worker thread normally this would happen if you access a UI control which is created in Main thread and accessed from different thread. try below code

 Dispatcher.Invoke
                    (
                      new Action(
                          delegate()
                          {
                               BmpBitmapEncoder encoder = new BmpBitmapEncoder();    
                               encoder.Frames.Add(BitmapFrame.Create(cache)); 
    using (FileStream file = File.OpenWrite(fName))    
    {    
        encoder.Save(file);    
    }  
                          }
                          )
                    );
saurabh