Splash Screens , how could something so basic still be hard?

R

RvGrah

Many of my apps have thousands of records to load, sometimes from a
server in another state. I want to show a splash screen that will tell
my users the progress, such as, "Retrieving records from server...",
"Sorting Data for Display..." kind of like the splash screen in
Photoshop. I've come the closest with using the vb ApplicationServices
method, but it doesn't allow me to pass updates to the splash screen.
In general, methods that launch from Program.cs seem a bit hard to
apply.

I really want to code this from the code of the form loading the data.
I've also dabbled with using a BackgroundWorker thread to load the
data and then close the splash screen when it's all loaded, but I
can't seem to pass the message text to show in the progress descriptor
label in the splash screen, in fact that label paints white and
doesn't show any text at all. Has anyone seen a good example
(preferably recent, vs2008) that shows how to do this? It doesn't have
to be simple although I'd like to be able to understand how it
works ;-)

I also don't want to cheat and just program the splash screen to show
for so many seconds, because sometimes the form loads in < 1 second,
sometimes as long as 6-10 seconds.

Bob Graham
 
M

Michael B. Trausch

Many of my apps have thousands of records to load, sometimes from a
server in another state. I want to show a splash screen that will tell
my users the progress, such as, "Retrieving records from server...",
"Sorting Data for Display..." kind of like the splash screen in
Photoshop. I've come the closest with using the vb ApplicationServices
method, but it doesn't allow me to pass updates to the splash screen.
In general, methods that launch from Program.cs seem a bit hard to
apply.

I really want to code this from the code of the form loading the data.
I've also dabbled with using a BackgroundWorker thread to load the
data and then close the splash screen when it's all loaded, but I
can't seem to pass the message text to show in the progress descriptor
label in the splash screen, in fact that label paints white and
doesn't show any text at all. Has anyone seen a good example
(preferably recent, vs2008) that shows how to do this? It doesn't have
to be simple although I'd like to be able to understand how it
works ;-)

I also don't want to cheat and just program the splash screen to show
for so many seconds, because sometimes the form loads in < 1 second,
sometimes as long as 6-10 seconds.

Bob Graham

Can you not just use it like a normal window?

e.g., have the window be the window that is displayed by your
application at startup, and when the appropriate events have come to
pass, remove that window and instantiate/display your "real" window?

That seems to be the approach I am able to find anyway:

http://www.programmersheaven.com/2/FAQ-WinForm-Splash-Screen
http://www.codersource.net/csharp_splash_screen.aspx

HTH,
Mike
 
M

Michael B. Trausch

[...]
That seems to be the approach I am able to find anyway:

http://www.programmersheaven.com/2/FAQ-WinForm-Splash-Screen

This is the most basic implementation of a splash screen one might
come up with. It has the unfortunate flaw that aside from getting
the splash screen to display once, there is no message pump to allow
for further GUI interactions. For example, if the splash screen, or
any other part of the UI, winds up needing to be redrawn (e.g.
someone drags a window over it), it won't be able to.

.... add code to do that? That's what you're supposed to do with GUI
components is hook into them and fit them to your needs. From your
response I am guessing that this isn't as easy to do with WinForms as
it is in GTK, were you create a Window and then either have it poll or
have it subscribe to signals that will update call code (that you
write) to update it. Repainting comes for free.
This one is marginally more flexible. In particular, it creates the
splash screen itself on a different thread, and then uses
ShowDialog() (which has a message pump built-in) to display it. On
the other hand, other than that it's not a very good example. It has
some serious thread mis-use problems (one should not use
Thread.Abort() to terminate threads, nor does it make any sense to
use Thread.Sleep() to wait for a thread to exit...use Thread.Join()
if you absolutely need that behavior, and don't write code that has
to wait on a thread to exit if you can at all help it).

Like the first example, it also provides no help to anyone trying to
have updates from one thread be presented to the use in a window
being shown from another thread.

Does WinForms not have a standard mechanism for that? Can't you throw
events or signals or something from one thread and catch them in
another?

--- Mike
 
M

Michael B. Trausch

have it subscribe to signals that will update call code (that you
write) to update it. Repainting comes for free.

I really need to proof before I send. That should read:

"... subscribe to signals that will call code (that you write) to
update it."

--- Mike
 
C

Cor Ligthert[MVP]

There have been numerous discussions in this newsgroup on the topic of
handling background tasks and using the Background Worker class.

But your main form should stop until your records are retrieved from the
server.

You can do this in two way.
Easy
Difficult

The Easy way is mostly a slight way shifting of the way you think.
While loading. your program has not to go on and show the splash screen (and
progress).
Your main class should stop and there is no need that it is responsive as
long as the splash screen is.
You should be able to stop the loading and the main program

Then simple move the loading to your splash screen (by references of course
to a class or an independent layer, not the complete code in your splash
screen).
Then as you do that in the code Peter has showed (without the sleep)
everything is solved.
And don't forget to tell the main class to cancel as that is done in the
splash screen.

The difficult way is try to do everything in your main class forgetting
everything what has to do with OOP and create a splash screen with a
background worker.

jmo

Cor
 
M

Michael B. Trausch

In short, the OP seemed to expect that there should be some special way
of dealing with splash screens, and I was merely seeking to show that
they, well, aren't. I had to confirm this for myself, though, since I
don't do WinForm programming.

Anything else in the examples is pretty much irrelevant. I assume that
the OP knows how to use a "regular" window, and so I assume also that
they know how to interact with it. Being a C# group and not a WinForms
or Windows GUI group, I think that's a reasonable expectation. Anyway,
more below, though it's probably firmly in the "off topic" category
since this is a C# group, and not a Win32, *nix, or GUI programming
group.

On Fri, 17 Apr 2009 16:58:42 -0700, Michael B. Trausch

[...]
That seems to be the approach I am able to find anyway:

http://www.programmersheaven.com/2/FAQ-WinForm-Splash-Screen

This is the most basic implementation of a splash screen one might
come up with. It has the unfortunate flaw that aside from getting
the splash screen to display once, there is no message pump to
allow for further GUI interactions. For example, if the splash
screen, or any other part of the UI, winds up needing to be
redrawn (e.g. someone drags a window over it), it won't be able to.

... add code to do that?

I don't know what you mean. You can always add code to "that",
whatever you mean by "that".

You say that there "is no message pump to allow for further GUI
interactions". What does that mean? Can you not create a form and
handle events in the application's startup routine to trigger updates
to it? If so, that doesn't make sense to me. Maybe the better
question is, how and why would you create and display a form without
having a main loop to do the initial painting of it and subsequent
management of it?
Again, not sure what your point is here. There's no well-defined
meaning for "hook into them". All of the .NET GUI classes provide
some kind of mechanism for customization, and all mechanisms
necessarily have their limits.

None of that seems relevant to your question; my point is that the
example given doesn't answer any of the questions YOU appear to
have. As such, it's not that relevant a code sample in terms of the
question you asked.

I was wondering why the OP expected a splash to be any different from a
window in the general sense.

Those were just the first two examples (of thousands) that I found; I
was pointing the OP at them to prod more searching to find better
answers, which is what I'd expect to do when I come across a problem.
At the very least, they show that you just use a regular window, which
is what I thought should have been the case in the first place; that's
how its done elsewhere that I know of.

Hooking in, of course, assumes that you have some sort of main loop
running and processing things for you. Obviously this means that
you're going to be working (at a lower level) with callbacks, and at a
higher level with signals and/or events of some form or another. In
GTK, for example, everything is a signal. You get focus, you get a
signal; you lose it, the same. You get a click, that's a signal, too.
And for all of the above, the main loop has to be running or you can't
even be initially painted.
I don't know what "GTK" is supposed to refer to. However, if it's
some kind of library, I suppose it's possible that it abstracts away
the thread affinity aspects that are inherent in Windows for GUI
objects (and which are inherent in many other GUI APIs, including
Java, and both Carbon and Cocoa on the Mac). The .NET APIs, both
Forms and WPF, are "closer to the metal", and expose the same thread
affinity issues that are present at the lower level.

GTK is a portable widget library, originally from the world of
UNIX-like systems. It's the basis of the GNOME desktop environment
and the GIMP graphics program. It's bindings for the CLR are called
GTK#, and are portable to UNIX-like systems, Windows, and OS X, as well
as anything that has a reasonably POSIX-complaint environment and X11.
As far as "repainting comes for free", that's not true in any API.
I'm sure it's not true even in "GTK". But, in all of the major
APIs, repainting is trivially handled by providing some kind of
responder. In the native API, that means handling the WM_PAINT
message. In .NET Forms, that means overriding OnPaint() or handling
the Paint event. Similar mechanisms exist in the other APIs. It's
about as close to "free" as you'll get.

GTK handles the details for exposure events and the like in its main
loop implementation. You don't handle any of that unless you're
creating purely custom widgets, and then of course you must. Widgets
take care of themselves in GTK, which is built on top of GDK, which
itself can run on Cocoa, X11, or Win32. As long as the main loop is
running, you will be repainted. If you have to do something in the
main thread that will take a long time, that means calling the main
loop at intervals to handle those things, or you'll look dead (e.g.,
not responding to a window ping or not accepting keyboard or mouse
input).
Once you've correctly installed a paint handler according to the API,
then the object will receive the paint "signal" any time it's
required. But, for this to happen, _something_ somewhere needs to
respond to the OS and forward that information to the object. In
Windows, that means a thread has to be in a message pumping loop, and
the way that works in .NET for the Forms objects is to call
Application.Run() (which the default template places in the Main()
method of Program.cs).

So, all that's required, if I understand you correctly, is to so some
very fast and early init, set up the splash screen form, enter the main
loop, and then have the form kick off the rest of the init that it
needs. That's exactly what one would do in GTK, anyway. The
implementation details are pretty well irrelevant---you could use a
single thread and call iterations of the main loop (assuming that
WinForms permits you do to that), or you can have a thread that the
splash screen spawns to handle its work and just take communication for
it. You could even use a design wherein you have a named pipe and a
sibling or child process that handles some of the work, and you get
data on progress over the named pipe, if you have another process doing
cache management or something for you. Depends on the requirements of
the particular implementation.

That said, a splash screen isn't generally any more complex than a
raster image of some sort, possibly one or more labels, and possibly
one or more other stock widgets used to signify progress, maybe another
label or a progress bar or an animated graphic for something that is
indefinite and doesn't map well to percentages. I don't see why you'd
have to set a paint handler at all; standard widgets should be managing
their painting all on their own.
The GUI object responds to various system events, including
repainting and user input, through this message pumping loop. The
loop retrieves a message from the message queue (aka "event queue",
"signal queue", etc. depending on the actual platform) and dispatches
it to the object. Until the object returns from handling that
message, no other messages can be processed.

This all happens on the thread where the GUI object was created.
The message queue is per-thread, and the queue is selected according
to what thread was used to create the GUI object. A message pumping
loop running on thread A will never see messages for objects created
on thread B.

So, there are two important design points here:

-- A GUI object is tied to the thread on which it was created,
in a fundamental way; interactions with the object have to happen on
that thread -- Code that responds to the various messages that are
sent to a GUI object must return in a timely manner, to allow the
message pumping loop to continue dispatching messages

Interesting. So, if GUI objects are tied to threads that they are
created in, the obvious solution is to have a GUI thread and other
threads that do work, with idle-time calls that check to see if the
work is actually done or check up on progress to be able to perform
updates, no? Or, expose an event or signal that can be called from the
spawned thread to actually inform the splash to update itself? These
would be how I would think to handle a splash in my own environment.

That said, the binding of widgets to threads sounds a bit strange to
me. If you're working with widgets, they should be accessible to
anything that is running in the main thread, assuming that a reference
to them can be obtained. Unless Windows separates threads into
different address spaces, I don't see how you'd be unable to reference
things in different threads. You just have to do so carefully.
Implications of those points are:

-- If you create an object on the wrong thread, one without a
message pumping loop, then no messages will ever be dispatched to
that object, including those for repainting and user input
-- Until you return from a message handler, no other messages
for ANY object on that thread can be dispatched, including those for
repainting and user input

Failure to note both of those implications can result in a UI that
appears to be "stuck" and unresponsive.
Right.

Even "GTK" is going to be subject to these limitations. If it does
abstract them away from you the user, it would have to do so by using
a different thread for each message dispatched to a GUI object (to
avoid blocking the message pumping loop), and by funneling all of the
GUI operations to a specific thread, to ensure objects are able to
receive and process messages sent to them.

GTK handles GDK events and GTK events. GDK handles events from the
underlying window system (e.g., Cocoa, X11, or Win32) and its own
events (which are called "signals", and which native events are
communicated as to GTK). GDK is built on top of GLib, which provides a
portable main loop and signal passing mechanism that isn't terribly
difficult to use. 90% of the things you'll do there you do as either
call backs or when there is idle time; anything that takes up a
noticeable amount of time, you either block for a bit (not recommended)
or spawn a thread to do the work.

If you frequently use threads for certain repetitive purposes, then
your application will usually contain threads that stay alive
throughout the program that handle these tasks. Mostly, this means
that you use a thread for I/O, and a thread that handles most
everything else, which runs the main loop. If you write a
single-threaded application, then you have to take additional steps to
ensure that you remain responsive. Those would include asking the
operating system to read data, and then polling for that data during
idle time in the main loop using a select() on the file descriptors.
(Does Win32 provide for such a thing?)
Whether "GTK" does all that, I don't know. I would be surprised if
it does the former (though it could be done in a reasonably efficient
way by using a thread pool), but it's possible it at least provides
the latter (which, if you're writing a full-blown GUI library that
completely hides the underlying Windows mechanisms used, probably
isn't that much extra effort).

GTK provides its own mechanisms; it doesn't use Win32 widgets on
Windows, though it might use lower-level mechanisms; it's only
dependency on a POSIX system is its own rendering utilities (Cairo,
Pango, FreeType, and various graphics and support libraries for things
like Unicode). However, its own widgets can be themed to look and feel
native. The upshot is that its buttons are handled programmatically
identically on every platform that GTK has been ported to, which is a
great number of them.
In any case, none of this is particularly challenging or inefficient
in .NET. You just have to know what you're doing. Until you do,
IMHO you should avoid jumping to conclusions and what is and what is
not "as easy to do with WinForms" as it is in some other library
you're used to using.

I'll wholeheartedly admit that I know very little about WinForms; I
simply don't use it because I only write and work on software that is
portable in nature, and I use GTK for GUIs (and most often, write
event-driven but non-GUI software). That said, I have worked with GTK
both within and outside of the CLR, and find it to be pretty
straightforward and easy to use.

That said, what I understand of WinForms is that it is a framework for
Windows application development on top of the CLR, just as GTK and its
associated components provide a framework for more-or-less portable
application development on top of the CLR. Both types of programs can
use the base class libraries, and both implementations, while for
similar purposes, have very different implementations and thus APIs. I
think you made the assumption that GTK is an abstraction of Win32; it
is not---it's a complete framework that sits on top of a base low-level
system. An application wouldn't use both at the same time (at least,
not wisely) since there would be two entirely different main loops
running, performing different things. While WinForms is (somewhat)
portable because other CLR implementations provide versions of its API
with varying levels of compatibility, it's not as portable as GTK,
within or outside of the CLR.
Of course it does. I've provided a number of specific examples and
pointers in my previous reply to your post.


You should avoid using the words "throw" and "catch", since those
imply exception handling, which is a completely different issue. But
otherwise, yes...as I've said, you not only can marshal GUI handling
from one thread to another, it's essential that you do so.

Don't know why you're talking about marshaling anything. Maybe "raise"
would be more appropriate for signals, but that terminology is also
used for exceptions in various environments; "handle" may be a
better term also for signals, but exceptions are handled as well. There
is a certain language barrier to be sure when crossing from platform to
platform or one development environment or framework to another, I
suppose.

It sounds like you're saying that a dialog in WinForms has its own
version of a main loop. That doesn't make sense to me; while you _can_
have more than one main loop, I am not sure why you'd want to, it
sounds like unnecessary complexity to me. It seems like you'd just
want to handle the dialog with its own set of callbacks that get
signaled from the main loop in the usual fashion.

In any case, I don't ever really use example code; I study it and think
about it when I need to refer to it, and then I turn around and
implement something that fits with what I need, which very often only
borrows tiny bits of idea from the original example. I expect others
(perhaps in err) to think the same of examples.

I don't think programming is a copy and paste sort of thing,
myself---and so citing example is, IMHO, only a beginning of something,
and never is it something I'd turn around and use unless I understood
it well and know exactly why I'd want to use it verbatim. That is of
course due to the sheer number of examples out there that are far less
than adequate for usage in anything serious. Examples are good for a
high-level overview, but of course that high-level overview is
meaningless if you don't have any idea as a programmer what you're
doing. I assume that a programmer can take from any example exactly
what they need and nothing more.

--- Mike
 
B

Ben Voigt [C++ MVP]

If you frequently use threads for certain repetitive purposes, then
your application will usually contain threads that stay alive
throughout the program that handle these tasks. Mostly, this means
that you use a thread for I/O, and a thread that handles most
everything else, which runs the main loop. If you write a
single-threaded application, then you have to take additional steps to
ensure that you remain responsive. Those would include asking the
operating system to read data, and then polling for that data during
idle time in the main loop using a select() on the file descriptors.
(Does Win32 provide for such a thing?)

It does have such mechanisms. The mother of them all is
MsgWaitForMultipleObjectsEx, and it is inexcusable for any framework to not
use that powerful function to build its main message loop. .NET uses
PeekMessage (IIRC, might be GetMessage) and as a result cannot dispatch APCs
or wake the GUI thread on (file) handle activity.

For the task at hand (displaying progress updates to a splash/loading
screen), it would be entirely suitable to create the window (and its handle)
and post a message to it (with .NET that'd be BeginInvoke). Then enter the
main message loop (in .NET it's Application.Run). Your startup code
specified in the call to BeginInvoke will then run. It should do a piece of
the processing, then post a message (BeginInvoke again) if it didn't
complete, then return to let the main message loop continue running. After
processing any paint messages, click on Abort button, etc, the posted
message will result in your startup code being called to do the next step.
This is far easier to manage than a background thread because now you have
fixed interruption points -- there's no true parallel access to the data.

Of course threading is needed in order to scale to multiple cores... but for
programs which are I/O bound, threading does more harm than good.
 
T

Todd Carnes

Michael said:
[...]
That seems to be the approach I am able to find anyway:

http://www.programmersheaven.com/2/FAQ-WinForm-Splash-Screen
This is the most basic implementation of a splash screen one might
come up with. It has the unfortunate flaw that aside from getting
the splash screen to display once, there is no message pump to allow
for further GUI interactions. For example, if the splash screen, or
any other part of the UI, winds up needing to be redrawn (e.g.
someone drags a window over it), it won't be able to.

... add code to do that? That's what you're supposed to do with GUI
components is hook into them and fit them to your needs. From your
response I am guessing that this isn't as easy to do with WinForms as
it is in GTK, were you create a Window and then either have it poll or
have it subscribe to signals that will update call code (that you
write) to update it. Repainting comes for free.

GTK+ has C# bindings. You could use it.
 
R

rvgrahamsevatenein

Thank you for all your responses. I have developed a process where I
set the main form to open Minimized. I then show the splash screen
before launching into all the data getting and displaying on a
background thread. When the backgroundWorker reports that it is
finished, I close and null the spalsh screen and un-minimize the main
screen. Part of why I'm doing this is so that the main window can be
restored and have any error messages show, as well as allow the user
to close the main window should something go wrong. Once I'm
comfortable that I have everything working properly I will probably
move the splash screen "Show" to right after InitializeComponent so
that the main window does not need to show in the taskbar until it's
actually ready to be interactive. I'm also looking at using the
message pump to invoke the splash screen to update it's progress
label. I realize I'm only partially using the good advice several of
you have given, but I'll get there soon I hope! At least what I'm
doing at this point is working as I (currently) intend it to!

Bob Graham
 
B

Ben Voigt [C++ MVP]

Peter Duniho said:
[...]
Of course threading is needed in order to scale to multiple cores... but
for programs which are I/O bound, threading does more harm than good.

That's not true. In fact, for i/o use of threading can be the best way to
provide a scalable program. For example, using IOCP, which in turn
necessarily uses threading, is the most efficient way to handle Socket
i/o.

No. It's the most efficient way to do significant CPU-bound processing
triggered by socket I/O. I said "programs which are I/O bound", which
includes most database interfaces, many 3D games/applications which are
limited by GPU streaming, etc.
The scenario in which threading can "do more harm than good" is when each
i/o thread is targeting the same resource. E.g. reading from or writing
to the same hard drive. In that case, yes...having multiple threads
contending for the same resource _may_ slow things down. But, having
multiple threads using different i/o resources is very efficient, and done
carefully there can even be benefits when using multiple threads using the
same i/o resource, due to the OS's ability to consolidate various i/o
requests when it interacts with the resource itself.

And what part of that "consolidation" is not possible with overlapped I/O?
Threads have a performance penalty only, with no benefits, until your CPU
utilization starts approaching one entire core.
 
B

Ben Voigt [C++ MVP]

Peter said:
[...]
That's not true. In fact, for i/o use of threading can be the best
way to provide a scalable program. For example, using IOCP, which
in turn necessarily uses threading, is the most efficient way to
handle Socket i/o.

No. It's the most efficient way to do significant CPU-bound
processing triggered by socket I/O. I said "programs which are I/O
bound", which includes most database interfaces, many 3D
games/applications which are limited by GPU streaming, etc.

I suppose that depends on your definition of "CPU-bound". My
definition: more time is spent using the CPU than the i/o resource.

It means that throughput is limited by CPU performance.

Your definition is very confusing. How do you measure "time spent using the
I/O resource"?
But, even in a scenario where the i/o takes longer than the CPU cost,
using IOCP can benefit, due to efficiently managing the threads
processing the i/o. The classic example being a high-connection
network server. A single thread can be sufficient to handle hundreds
of thousands of active connections, but only if that single thread
isn't the only thread in your application.

Exactly what does having an additional thread buy you? I contend that on a
single core system, the optimum solution is single-threaded, for any
definition of optimum/cost function you care to use.
You seem to be using the term "threading" differently than I am. I
interpret your statements that discuss "threading" to mean "a program
with more than one thread". Merely having more than one thread does
_not_ imply a performance penalty in and of itself.

If you have multiple threads (ignoring any that never become runnable), then
you'll need to synchronize access to your data somehow. All synchronization
has some non-zero cost.
 
B

Ben Voigt [C++ MVP]

With respect to sockets, the particularly important part for the
purposes of this question is that there simply is no efficient way to
manage hundreds of thousands of sockets on a single thread, unless
one is using IOCP, which necessarily requires writing threaded code. The
alternatives simply have too much CPU overhead to be practical.

I don't know what makes you believe that overlapped I/O or APCs would have
more overhead than IOCP, let alone "too much to be practical".
 
B

Ben Voigt [C++ MVP]

Peter Duniho said:
I don't know what makes you believe that those are always feasible
strategies for the implementation.

Not 100% sure, but isn't kernel support for APCs the underlying mechanism
that makes IOCPs go?
 
B

Ben Voigt [C++ MVP]

Peter Duniho said:
Peter Duniho said:
On Thu, 23 Apr 2009 15:12:36 -0700, Ben Voigt [C++ MVP]

I don't know what makes you believe that overlapped I/O or APCs would
have
more overhead than IOCP, let alone "too much to be practical".

I don't know what makes you believe that those are always feasible
strategies for the implementation.

Not 100% sure, but isn't kernel support for APCs the underlying
mechanism that makes IOCPs go?

Not that I know of. IOCP is more of a thread scheduling thing than an
"interrupt" thing. I don't know what mechanism is used for actually
managing the completion queue, and maybe that's using APC, but that's at a
much lower level than the application sees and in any case still requires
the application provide a dedicated thread for the purpose.

APCs are a completion queue, no more and no less. They aren't
"asynchronous" at all, despite the name.
In any case, for APC to work, you need a thread in the correct state,
which isn't always possible.

Depending on what brain-dead libraries you're using that block execution
without entering an alertable wait, true. But those tend to cause problems
with IOCP as well, depleting the thread pool.
Beyond that, the fact is that all of the major, scalable server
implementations that I know of use IOCP. These are not implementations
for which complexity is a barrier; the people coding them can code
whatever is most effective. And they use IOCP, specifically because it
provides the performance they need.

I presume that these are all processing requests from many different clients
which are essentially independent of each other, so there is little or no
shared data? IOCP is good in that case because it scales well whether or
not you are CPU-bound.

But if you are sharing data and you know you are I/O bound, then staying
single threaded makes the sharing an awful lot simpler.

Consider the different between an e-commerce system (every user communicates
with the database and only indirectly with each other) vs an IRC or MMORPG
server (communication between users is frequent). In the latter case, a
single-threaded server implementation will be much much simpler and most
likely considerably more efficient. Ok, your server wouldn't be
single-threaded, you'd most likely have one thread per IRC room or per game
zone, because that's the natural region of communication. What you wouldn't
do is let a thread pool assign incoming packets to worker threads and
synchronize everywhere.
 
C

Cor Ligthert[MVP]

Ben and Peter,

I never understand why you guys want to use a backgroundworker when the
opacity of the mainform is zero.

(I mean in the situation of a splash screen, I use multithreading, for
instance in window services, before you misunderstand me)

Cor
 
C

Cor Ligthert[MVP]

Peter,
Huh? Your question doesn't make any sense. The opacity of the window has
nothing to do with whether using a thread is useful or not.
Probably I don't understand something: therefore how do you respond to an
invisible form?

Cor
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top