Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: C# Threading
Here is a dummed-down version of my problem.
I replicated the exact class structure and only included the necessary code.
 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Printing;
using System.Threading;
using System.ComponentModel;
 
namespace ThreadAndSpool
{
    class MyMainProcessClass
    {
        MyBackgrounWorkerClass bw = new MyBackgrounWorkerClass();
        public MyMainProcessClass()
        {
            bw.Start();
        }
    }
 
    class MyBackgrounWorkerClass
    {
        private BackgroundWorker _bw = new BackgroundWorker();
        private PrintHost _ph;
 
        public MyBackgrounWorkerClass()
        {
            _ph = new PrintHost();
            _bw.DoWork += new DoWorkEventHandler(bw_DoWork);
        }
 
        private void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            _ph.CheckHost();
        }
 
        public void Start()
        {
            _bw.RunWorkerAsync();
        }
    }
 
    class PrintHost
    {
        public PrintServer _hostingServer;
        public PrintHost()
        {
            _hostingServer = new PrintServer(@"\\" + Environment.MachineName, PrintSystemDesiredAccess.AdministrateServer);
        }
 
        public void CheckHost()
        {
            _hostingServer.Refresh();
        }
    }
}
 
The line containing:
_hostingServer.Refresh();
Causes the following runtime error:
"The calling thread cannot access this object because a different thread owns it."
 
I'm guessing that calling process is "MyMainProcesssClass" and that I have to implement a Dispatcher, but so far I've not been able to get around this error.
 
At request I have this dummed-down code in a VS2008 c# project.
Posted 25-Aug-11 2:41am
MatthysDT6.3K
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

Answering one of the follow-up questions: InvokeRequred can be called on any of the controls involved in the currently running UI. Usually it is called on the control which is used in the invocation following under "if".
 
Now, InvokeRequred is not really needed in most cases. If you call it from non-UI thread is will always return true. This method is needed only in one case: you put it in some method which sometimes is called from UI thread, sometimes in some other thread. People mistakenly attribute too much importance to this function.
 
I explained the mechanism of invocation in detail in my past solutions.
 
You cannot call anything related to UI from non-UI thread. Instead, you need to use the method Invoke or BeginInvoke of System.Windows.Threading.Dispatcher (for both Forms or WPF) or System.Windows.Forms.Control (Forms only).
 
You will find detailed explanation of how it works and code samples in my past answers:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^].
 
See also more references on threading:
How to get a keydown event to operate on a different thread in vb.net[^],
Control events not firing after enable disable + multithreading[^].
 
—SA
  Permalink  
Comments
Simon Bang Terkildsen at 25-Aug-11 23:52pm
   
Important information indeed +5
SAKryukov at 25-Aug-11 23:54pm
   
Thank you, Simon.
--SA
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

BackgroundWorker executes your tasks in a different thread than the one that creates it (and your PrintHost instance). You'll need to use InvokeRequired and Invoke to make cross-thread method calls.
  Permalink  
Comments
Abhinav S at 25-Aug-11 7:58am
   
Good answer. 5.
MatthysDT at 25-Aug-11 8:23am
   
Thank you Shameel, I'm new to Threading, on which object should I check the InvokeRequired property?
Shameel at 25-Aug-11 9:59am
   
I'm not sure if you are using UI elements here. This error typically occurs when you try to access UI elements from a thread other than the one that created them. In that case you'll use Control.InvokeRequired.
 
Where is the PrintServer class declared? What does it derive from?
MatthysDT at 25-Aug-11 10:03am
   
I don't have UI element in this project. I declare the PrintServer object globally in my PrintHostClass and instantiate it in the constructor.
PrintServer is a .Net class in System.Printing
(C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\v3.0\System.Printing.dll)
 
I'm beginning to think that that class is not thread safe.
 
If I declare the PrintServer (_hostingServer) within the CheckHost() method, I don't get the same error, but this is not ideal.
MatthysDT at 25-Aug-11 8:40am
   
If I discard the BackgroudWorker and run _ph.CheckHost within the Timer_Elapsed event of a System.Timers.Timer, I get the exact same issue, eventhough I'm no longer using threading.
Shameel at 25-Aug-11 9:53am
   
Because Timer too uses a different thread to run your code.
SAKryukov at 25-Aug-11 23:46pm
   
Agree, my 5 for the answer, but... please see my solution.
I answered about InvokeRequired and added detailed explanation to invocation itself. Some of this information is little known.
--SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 OriginalGriff 381
1 Sergey Alexandrovich Kryukov 245
2 Marcin Kozub 225
3 Praneet Nadkar 217
4 /\jmot 189
0 OriginalGriff 8,284
1 Sergey Alexandrovich Kryukov 7,407
2 DamithSL 5,614
3 Maciej Los 4,989
4 Manas Bhardwaj 4,986


Advertise | Privacy | Mobile
Web04 | 2.8.1411023.1 | Last Updated 25 Aug 2011
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100