Peter Duniho has brought this to us :
On Tue, 05 Feb 2008 07:14:34 -0800, Brad White
We obviously have a failure to communicate.
[...]
This is a unit test. The object that is running in the background
doesn't know whether there is a UI or not and shouldn't behave any
differently if there is. If it behaved differently, then it wouldn't
be a valid test.
Then the UI-specific behavior doesn't belong in the unit test.
We are in agreement on that.
What part of running a separate thread is UI-specific?
Well, for one, so far the only stated need to run this code on a separate
thread is having a GUI. Is there something about this code that otherwise
precludes simply running it on a single thread in a console application?
Let's put it this way.
I have a bckground worker in my app. There is no UI-specific
code, beyond using the background worker.
Then why are you using the BackgroundWorker?
My recollection is that it is possible to set up a synchronization context
for a thread that will allow the BackgroundWorker to operate without a
Forms-based GUI, but in a similar way to if you had one. But if I recall,
it's not all that simple to do and generally the BackgroundWorker is
specifically for cases where you have a Forms-based GUI.
If you have no Forms-based GUI, then typically it would be the case that
using a BackgroundWorker is unnecessary.
I want to unit test
this and run it as part of my suite. So it needs to run in a
console app.
I'm running into the same issue as this guy:
http://www.eggheadcafe.com/software/aspnet/29191764/backgroundworker-does-not.aspx
That guys appears to be writing a GUI application. I'm not clear on how
you're running into the same problem, given that your concern is
specifically about what happens when there's no GUI.
Beyond that, there is not generally a problem using BackgroundWorker in
non-Forms applications. If there is no synchronization context, the
BackgroundWorker will raise all of the relevant events on the same thread
used to run the DoWork event handler, rather than marshal the events to
another thread. But otherwise it works fine.
A quick look at the code you've referenced above shows that he is not
using the Forms classes correctly. In particular, he's creating a Control
instance without any containing Form, and he never enters a message pump
that would allow that Control instance to process messages sent to it. In
other words, he's lying to BackgroundWorker by claiming he's got a Control
that can be used to marshal events to a specific thread, when in fact that
Control is never available to receive events (or any window messages for
that matter).
If this is relevant to your own code, it means you are similarly misusing
the Forms classes. On the other hand, if you are not misusing the Forms
classes, then that example isn't relevant to this discussion.
That's the point. How do I get the background thread to communicate
with the foreground thread without any forms?
Short of creating a new synchronization context and pumping messages for
it, I'm not aware of any built-in way. It's not a common requirement.
It is not difficult to write your own solutions, but you should not bother
doing so unless there's a genuine need.
[...]
But there's no managed equivalent for a console application. Your main
thread does whatever it does straight through. There's no built-in
message pump loop that can be used to deliver invoke requests to an
object on the main thread.
Exactly. It would have to be written. That part is not difficult
and I've done it before in other languages. What I can't find is
what exactly that loop would call.
I'm not clear on this question. If you've implemented this before in
other languages, then you must have used mechanisms similar to those
available in .NET to do so. In .NET, you'd use those mechanisms as well.
I've already described one possible solution: a producer/consumer design
using delegates as the commodity.
This is a unit test of production code. How can it not be common
to need to test this? Is no one writing threaded code?
Lots of people write threaded code. But the only reason one would
typically need to execute code on a specific thread is in situations where
that requirement is imposed by .NET. And in those situations, .NET
provides a suitable mechanism for doing so.
Conversely, in the situations in which .NET provides no mechanism, it's
very rare to have the need, even when the code has multiple threads.
I can't change the architecture, just for this.
I doubt you need to. But you haven't offered enough details for me or
anyone else to say for sure whether doing so would be necessary or if
there's some alternative approach.
You have asserted a need to execute code on a specific thread. I have
explained that there's no convenient way to do this outside of a
Form-based GUI application (you can use a synchronization context, but I
wouldn't call that convenient).
I still question your assertion of the need stated, but assuming that's
really a need, you are stuck either implementing this yourself or using a
synchronization context to handle things. Neither approach is really all
that difficult, and IMHO wouldn't represent a huge change in architecture
(not only would it not be a lot different than using a Form-based GUI, it
should plug into the code in much the same way if done correctly). But
it's not what I'd call convenient, and like I said: I doubt you really
need to do this.
If the above doesn't give you enough information to proceed, you really
should post a concise-but-complete sample of code that demonstrates what
you're trying to do and what doesn't work. Please note: every word in
"concise-but-complete" is important. The code should be brief, the
shortest code required to demonstrate exactly the issue, without any
additional stuff in it. But it also needs to be able to be compiled and
run without any additional effort on anyone's part. And of course, in the
context of any such sample, you need to explain very clearly what parts
work as desired, what parts don't, and why.
Pete