mfc >> create controls in a seperate thread

by Igor Tandetnik » Sat, 22 Nov 2003 06:43:54 GMT

"Sebastian Faust" < XXXX@XXXXX.COM > wrote in message
news:bpm2rn$ngh$02$ XXXX@XXXXX.COM ...
> I am currently writing an application, which have to create on
run-time a
> new Control ( for example a CEdit-Control ) in a sperate thread.

Don't even think of doing that. Having a child window created by a
thread different from that of its parent window is one of the easy ways
to get a deadlock in Windows. On top of that, MFC uses thread-local
storage heavily and is not thread-safe.
--
With best wishes,
Igor Tandetnik

"For every complex problem, there is a solution that is simple, neat,
and wrong." H.L. Mencken




mfc >> create controls in a seperate thread

by Sebastian Faust » Sat, 22 Nov 2003 06:49:49 GMT


Why isnt it a good practice?

What can be another solution, cause what I am doing is that over the serial
port some data comes in, and if for example I receive over the COM-Port the
command EDIT I will create a new control. I listen to the COM-Port in
another thread, not to block the main thread.

Bye
Sebastian





mfc >> create controls in a seperate thread

by Sebastian Faust » Sat, 22 Nov 2003 06:51:00 GMT

Hi,

what what then be a solution to my problem?

Bye,
Sebastian




create controls in a seperate thread

by Igor Tandetnik » Sat, 22 Nov 2003 07:11:12 GMT





Post a message from the worker thread to the main window, have the main
window create the control.
--
With best wishes,
Igor Tandetnik

"For every complex problem, there is a solution that is simple, neat,
and wrong." H.L. Mencken




create controls in a seperate thread

by Sebastian Faust » Sat, 22 Nov 2003 07:13:28 GMT

Hi,

"Ali R." < XXXX@XXXXX.COM > schrieb im Newsbeitrag

it
a
Sadly it doesnt work either with the m_hWnd. Any other ideas?

Thanks in advance
Sebastian




create controls in a seperate thread

by Scott McPhillips [MVP] » Sat, 22 Nov 2003 07:24:54 GMT




Your plan is way beyond good practice - there are several reasons that
it cannot work. A window (the edit control) needs a message pump. So
even if you could create a CEdit in a non-MFC thread (you can't) the
window would not work in your thread because it doesn't have a message
pump.

You must create the CEdit in the GUI thread. When your serial thread
wants the GUI thread to do something it should post a user-defined
message to the GUI thread. See...

http://www.mvps.org/vcfaq/mfc/12.htm

--
Scott McPhillips [VC++ MVP]



create controls in a seperate thread

by Sebastian Faust » Sat, 22 Nov 2003 10:00:39 GMT

Hi,

disaster.
previous sentence (I'm
all the
effort.
You really have lots of interesting articles on your web-page. I read about
defining User-Defined-Messages and wonder how to use the macro:
DECLARE_USER_MESSAGE

Can you give me an examle how to use it?

I tried the following, but that doesnt work:
pProcessor->m_pWnd->SendMessage(DECLARE_USER_MESSAGE(UWM_CREATE));

What is wrong with that?

Thanks in advance
Sebastian




create controls in a seperate thread

by Joseph M. Newcomer » Sat, 22 Nov 2003 14:23:51 GMT

The article shows that to use my DECLARE_MESSAGE macro, you have to have done a #define of
a name which is the string for the Registered Window Message. That is, in a header file
you put

#define UWM_DOSOMETHING_MSG _T("UWM_DOSOMETHING-guidhere")

and then you can write

DECLARE_MESSAGE(UWM_DOSOMETHING)

which actually expands to

static UINT UWM_DOSOMETHING = ::RegisterWindowMessage(UWM_DOSOMETHING_MSG);

The trick that makes it work is the naming convention of putting _MSG at the end of the
#define constant.

Then you can use that name in a SendMessage:
wnd->SendMessage(UWM_DOSOMETHING, someWvalue, someLvalue);
joe

On Sat, 22 Nov 2003 03:00:39 +0100, "Sebastian Faust" < XXXX@XXXXX.COM >



Joseph M. Newcomer [MVP]
email: XXXX@XXXXX.COM
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm


create controls in a seperate thread

by Alexander Grigoriev » Sat, 22 Nov 2003 23:50:11 GMT

Registered message is an overkill for internal messages. Better to use some
from WM_APP range.



done a #define of
a header file
::RegisterWindowMessage(UWM_DOSOMETHING_MSG);
the end of the




create controls in a seperate thread

by Joseph M. Newcomer » Sun, 23 Nov 2003 17:54:55 GMT

This is not a reliable method. In fact, it is so unreliable that it cost one of my clients
quite a lot of money to fix; I'd been using WM_APP (I was younger and more innocent in
those days), and they added a third-party DLL that also used the same WM_APP messages.
Their programmer wasn't clever enough to figure it out; eventually, after a couple weeks,
they called me, and I found it it a few hours. That's when I stopped using WM_APP
messages. I consider it extremely important that a program remain robust under
maintenance, and this means that I won't introduce features that have this potential for
conflict.
joe






Joseph M. Newcomer [MVP]
email: XXXX@XXXXX.COM
Web: http://www.flounder.com
MVP Tips: http://www.flounder.com/mvp_tips.htm


Similar Threads

1. create controls in a seperate thread

2. Changing ProgressBar in a seperate Thread

Hello,

I want to change a ProgressBar in a separate Thread.

My current code is the following:

private void changeProgressBarThread()
{
     changeProgressBar();
}

private void changeProgressBar()
{
     toolStripProgressBar1.Maximum = 100;
     for (int i = 0; i <= 100; i++)
     {
        toolStripProgressBar1.Value = i;
            if (i == 100)
               {
                for (int j = 100; j >= 0; j++)
                {
                   toolStripProgressBar1.Value = j;
                }
               i = 0;
            }
        }
}


private void button1_Click(object sender, EventArgs e)
{

     ThreadStart thrdDeleg1 = new ThreadStart(addDataSetThread);
     Thread addDSThrd1 = new Thread(thrdDeleg1);

     ThreadStart thrdDeleg2 = new ThreadStart(changeProgressBarThread);
     Thread addDSThrd2 = new Thread(thrdDeleg2);

     addDSThrd1.Start();
     addDSThrd2.Start();

     while (addDSThrd1.IsAlive)
     {
	if(!addDSThrd1.IsAlive)
             addDSThrd2.Abort();
     }
     addDSThrd1.Join();

     string[] row = new String[3];
     row[0] = searchText_;
     row[1] = results_.count.ToString();
     row[2] = "0";
     dgViewData.Rows.Add(row);

}


My problem is now, that I cannot use the toolStripProgressBar1 object:

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

I understand the error message but... How can I fix the error?
I do not know how to update my progress bar if I cannot update it in my 
seperate thread.

How do you do that?


It would be nice if you could give me a small example.


And my other question concerns the following code lines:

    while (addDSThrd1.IsAlive)
     {
	if(!addDSThrd1.IsAlive)
             addDSThrd2.Abort();
     }


I think these lines of code are not very well/ secure,
because it looks bit like an endless loop.

How do you let another thread (here my progress bar thread) stop if a 
long calculation in another thread is finished?



Regards,

Martin

3. how to run a window on a seperate thread - CSharp/C#

4. Timer doesn't work in seperate thread

I've set up a seperate thread and put a timer in it but for some reason it's 
tick event is never fired. This is what I have...

...
Thread timerThread = new Thread(new ThreadStart(startTimer));
timerThread.Start();
...

private void startTimer()
{
System.Windows.Forms.Timer idleTimer = new System.Windows.Forms.Timer();
idleTimer.Interval = 1000;
idleTimer.Tick += new System.EventHandler(idleTimer_Tick);
idleTimer.Start();
}

private void idleTimer_Tick(object sender, System.EventArgs e)
{
System.Console.WriteLine("Time Reached!");
}

If I put a breakpoint on the WriteLine statement it never gets run and I 
can't figure out why.

Any ideas?

Darrell

5. Windows Form in seperate thread - CSharp/C#

6. UserControl always run in seperate thread

I need a control to always run in a separate thread from the application. 
I'm not too sure where to begin with this since the control could be dropped 
on the form at design time.

One possible idea I had was to wrap my control in another control which 
creates the thread and than creates the control.

Any suggestions?

-Joe 


7. Fully functional form in a seperate thread - CSharp/C#

8. Loading webbrowser in seperate threads

I have a need to create an instance of the webbrowser control in seperate 
threads and display each on seperate forms in an MDI application.  The 
hosting site knows if the browser is in the same thread and will not isolate 
the sessions for me.  I can open seperate instances of IE or Netscape and 
the site works fine, however it will not work fine in tabbed pages.  So I 
want to be able to have a singular application with mutliple browsers.

I think that I am creating the instance of my usercontrol in the wrong 
manner but am unable to figure out what I need to change about it.

I am using C#'08

Thanks in advance and Happy Holidays

What I have done is:

project1 the dll

1.  Create an interface to interact with the webbrowser control

     public interface IMyBrowser
     {
        void StartUp();
      }

2.  Create a custom usercontrol that hosts the webbrowser control that 
implements the interface

    public class MyBrowser: UserControl, IMyBrowser
    {
      public void StartUp()
      {
        this.browser.Navigate(@MyWebsite);
      }
    }

Project2 the executable

1.  Added a reference to the dll
2.  Created a mdi form to host the mdi children
      void MenuItemClick(...)
      {
         frmBrowser f = new frmBrowser();
         f.mdiParent = this;
         f.Show();
      }

3.  Created a mdi child form to host the browser control from the dll
      public void frmBrowser()
      {
        InitializeComponent();
        MyDll.MyBrowser instance = 
(MyDll.MyBrowser)GetInstance<MyDll.IMyBrowser>();
        if(instance != null)
       {
          this.controls.add(instance);
          instance.dock = DockStyle.Fill;
          instance.StartUp();
       }
      }

    private object GetInstance<T>()
    {
      object instance = null;

      string[] files = 
Directory.GetFiles(System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), 
"*.dll");

      foreach (string file in files)
      {
        Trace.WriteLine("Loading " + file);
        try
        {
          Assembly assembly = Assembly.LoadFile(file);
          foreach (Type type in assembly.GetTypes())
          {
            if (!type.IsClass || type.IsNotPublic) continue;
            Type[] interfaces = type.GetInterfaces();
            if (((IList)interfaces).Contains(typeof(T)))
            {
              instance = Activator.CreateInstance(type);
              break;
            }
          }
        }
        catch (Exception ex)
        {
          //throw;
        }
      }
      return instance;
    }