|
See here[^].
BTW: For this kind of questions you should first ask "uncle Google".
Regards
Nuri Ismail
|
|
|
|
|
Hi all,
i m using system tray icon for my application ,but when i run my application on windows xp the ballon of system tray icon not displayed,while its working fine in case of vista.
please help me how can i show ballon.
thanks in advance.
To accomplish great things, we must not only act, but also dream;
not only plan, but also believe.
|
|
|
|
|
Without seeing your code, I have no idea what the mistake you're making is.
But if it works under Vista, I would guess you're using either a vista only function (unlikely), or using Vista only members of NOTIFYICONDATA.
My code from waaaaaay back when:
NOTIFYICONDATA niData;
memset (&niData, 0, sizeof(niData);
niData.cbSize = sizeof (niData);
niData.hWnd = m_hFrameWnd;
niData.uID = 99;
niData.uFlags = NIF_ICON;
niData.hIcon = m_hTaskBarIcons [0];
Shell_NotifyIcon (NIM_ADD, &niData);
http://msdn.microsoft.com/en-us/library/bb773352%28VS.85%29.aspx[^], and I see that there is indeed a vista extension.
#if (NTDDI_VERSION >= NTDDI_VISTA)
HICON hBalloonIcon;
#endif
So, you pass the size of the vista only structure in cbSize, and XP goes "huh".
Read the rest of the article, and it will point you to a constant that defines the size of the structure that XP can handle.
Good luck,
Iain.
I have now moved to Sweden for love (awwww).
If you're in Scandinavia and want an MVP on the payroll (or happy with a remote worker), or need cotract work done, give me a job! http://cv.imcsoft.co.uk/[ ^]
|
|
|
|
|
I m taking help of this article for system tray icon
Adding Icons to the System Tray[^]
To accomplish great things, we must not only act, but also dream;
not only plan, but also believe.
|
|
|
|
|
It should work on XP.
Do you have SP2 installed?
«_Superman_»
I love work. It gives me something to do between weekends.
|
|
|
|
|
What is the safe way to get the m_hThread handle?
One of few cases that construction hangs even if I change INFINITE to a second or so. It should be something with m_SomeThread object.
m_SomeThread is stored in MFC dialog.
Upon the user click, the AfxBeginThread is called, and m_SomeThread is assigned its return value.
I'm sure the thread does not hang in its body, as it posts the message to the dialog to report that it is finished.
Before creating another thread, the function waits for a single object in case user clicked too early and the thread has not yet terminated.
And one of few such calls the application freezes completely.
Чесноков
|
|
|
|
|
Did not really understand your question?
But I'm guess it has something to do with GetExitCodeThread[^].
«_Superman_»
I love work. It gives me something to do between weekends.
|
|
|
|
|
|
Hi Yuriy,
Chesnokov Yuriy wrote: What is the safe way to get the m_hThread handle?
If the pointer to the thread is valid and the thread has not exited then the m_hThread handle is valid. You can use the GetExitCodeThread Function[^] to check if the thread is still active.
Chesnokov Yuriy wrote: And one of few such calls the application freezes completely.
What does your thread do? Are you interacting with a GUI thread?
Best Wishes,
-David Delaune
|
|
|
|
|
Hi Randor,
99% of cases the thread is already terminated, when the WaitForSingleObject() is called.
GetExitCodeThread() also uses CWinThread object handle.
I presume if the thread is terminated and the examination of the property m_SomeThread->m_hThread leads to some hanging in my case.
The thread simply do some math calculations as the user click the button, then prints the results of calculations to the GUI by means of PostMessage. The result is in the message params and GUI MFC juts put that result into the main dialog window.
So the user click the button, thread do some clever math in about 1-2 seconds, then the results are sent by PostMessage.
I did not want to go into disabling that button, while the thread is not finished, so I tried to use WaitForSingleObject() to make sure the thread will not be called twice if user clicks the button, before the thread terminated
Many thanks.
Чесноков
|
|
|
|
|
Here is what my instincts are telling me.
1.) You create your thread and it begins your small intensive calculation.
2.) Your parent thread is preempted and loses its CPU quantum slice before WaitForSingleObject is called.
3.) Your calculation is completed and the thread exits.
4.) Your parent thread resumes WaitForSingleObject and begins waiting on an invalid thread handle.
I would suggest the following:
1.) Create your thread suspended.
2.) Duplicate the thread handle.
3.) Wait on the duplicated handle.
4.) Resume the thread.
Let me know if it solves your problem.
Best Wishes,
-David Delaune
|
|
|
|
|
Randor wrote: 1.) Create your thread suspended.
2.) Duplicate the thread handle.
3.) Wait on the duplicated handle.
4.) Resume the thread.
Better to create the thread suspended, set the CWinThread::m_bAutoDelete to FALSE and then resume the execution of the thread.
The CWinThread object will normally destroy itself when the thread exits and consequently close the thread handle. This is prevented by setting m_bAutoDelete to FALSE .
But it also means that the caller is responsible for deleting the CWinThread object when the thread has finished.
As always: more info here[^].
"It's supposed to be hard, otherwise anybody could do it!" - selfquote "High speed never compensates for wrong direction!" - unknown
|
|
|
|
|
Hi Roger,
Thanks for the comment. Yes what you have described is another valid method to avoid waiting on an invalid thread handle. Describing it as 'better' sounds like an opinion.
Best Wishes,
-David Delaune
|
|
|
|
|
Hi David,
Randor wrote: Describing it as 'better' sounds like an opinion.
Mmmm, it may be so, but I'd like to clarify my opinion.
If the OP's problem was that he called ::WaitForSingleObject() with an invalid handle, it would return immediately with WAIT_FAILED , so this cannot be the problem. If the handle is still valid ::WaitForSingleObject() will either return zero or wait as expected.
Your suggestion to duplicate the handle is to circumvent the fact that CWinThread will close the handle in its destructor, unless the m_bAutoDelete member is set to FALSE . In this case my opinion of 'better' is to fix it the MFC way since it was introduced by MFC.
I think it's cleaner and hence 'better', but whether that's 'better' or not is a matter of opinion.
For what it's worth I think the OP has created some kind of race condition that may end up in a deadlock where the spawned thread sends a message to the main thread. In the message handler call chain he then waits for the thread to finished.....
"It's supposed to be hard, otherwise anybody could do it!" - selfquote "High speed never compensates for wrong direction!" - unknown
|
|
|
|
|
Roger Stoltz wrote: If the OP's problem was that he called ::WaitForSingleObject() with an invalid handle, it would return immediately with WAIT_FAILED
This is not completely correct. The NT kernel recycles both window and thread identifiers (HANDLES). You can easily test this by creating a test dialog with 2 buttons. On the first button create a thread and on the second button end the thread. Rapidly press the buttons and observe the newly created thread sometimes has the same handle value in your traced output. It is the same for window handles... when they are closed the same value can be assigned to a window created in the near future.
An excerpt from: The Birth of a Thread: CreateThread[^]
Please do not make any assumptions about this identifier; all that is guaranteed is that while the thread is running, no other thread will ever have the same ID. The ID may be recycled later on after the thread has terminated.
Multithreading for Rookies[^]
Give Me a Handle, and I'll Show You an Object[^]
1.) The benefit of your option is the engineer does not need to call DuplicateHandle. On the negative side your option requires the engineer to manually perform the thread cleanup.
2.) The benefit of the other option is the engineer does no cleanup because m_bAutoDelete defaults to TRUE. On the negative side the engineer has to call DuplicateHandle and then CloseHandle when he is done waiting.
Anyway, this debate is meanlingless. If the presented scenario is what is actually occuring then both options presented are good options. This is the beauty of the internet and sites like codeproject.com where professionals can exchange ideas and their experience.
Best Wishes,
-David Delaune
|
|
|
|
|
Randor wrote: The NT kernel recycles both window and thread identifiers (HANDLES).
Yep, I know that it does.
I don't see how this is relevant in this scenario though; even if the handle gets recycled it can only have one state in the aspect of valid or invalid when ::WaitForSingleObject() is called, which would mean that if the handle should happen to be invalid when ::WaitForSingleObject() is called it would return WAIT_FAILED. That's why I still think my previous statement is correct even though you seem to think not.
Additionally, as I understood it, the OP waits on the thread handle before creating another worker thread (as he should).
Randor wrote: If the presented scenario is what is actually occuring then both options presented are good options.
Of course!
Randor wrote: Anyway, this debate is meanlingless.
Naah, you provided a perfectly acceptable meaning yourself:
Randor wrote: This is the beauty of the internet and sites like codeproject.com where professionals can exchange ideas and their experience.
Exactly and I really enjoyed our little discussion.
"It's supposed to be hard, otherwise anybody could do it!" - selfquote "High speed never compensates for wrong direction!" - unknown
|
|
|
|
|
Roger Stoltz wrote: I don't see how this is relevant in this scenario though
Is it *very* relevant. I am asserting that there is a small chance that immediately following thread termination it is possible for the same identifier to be assigned to another thread or kernel object. If you like I can create a sample application which continuously spawns/terminates a self deleting thread and then force a context switch before calling WaitForSingleObject. The alertable wait state will return 99% of the time and eventually deadlock. The cause of the deadlock will be a valid handle which is invalid in the context of the process calling WaitForSingleObject. I guess it would be better to use a different terminology as invalid seems to be confusing you.
As I have previously mentioned both of our excellent recommendations will avoid the deadlock.
Best Wishes,
-David Delaune
|
|
|
|
|
Well, what I have is a button click code:
1. if (m_SomeThread != 0) goto 2.
2. WaitForSingleObject(m_SomeThread->m_hThread, INFINITE);
3. m_SomeThread = AfxBeginThread(...)
The thread starts immediatly.
What I understood is if you create thread suspended and set autodelete to false, it will not be destroyed as the thread finishes.
In that case m_SomeThread->m_hThread will be valid and will not hang the GUI?
In that case it needs additional explicit thread destruction between 2. and 3. clauses.
Чесноков
|
|
|
|
|
Hi Yuriy,
Yes you understand correctly. The thread handle will be valid if m_bAutoDelete is set to FALSE. You will need to perform cleanup yourself of the m_SomeThread object.
Best Wishes,
-David Delaune
|
|
|
|
|
Randor wrote: As I have previously mentioned both of our excellent recommendations will avoid the deadlock.
David, no offence taken!
I find it interesting and there's a possibility that someone might learn something and it could be me.
However, I think you have misread my previous post (or possibly posts).
I figure this as I am still under the impression that the OP waits on the thread handle before spawning a new thread, as I've stated previously.
- or -
Do you really mean that you have experienced a scenario where you have a handle that:- you provide as argument to e.g.
::WaitForSingleObject() - is valid so the waiting function doesn't return
WAIT_FAILED immediately - has not assumed a signalled state (which would make the waiting function return immediately)
- becomes signalled, closed and recycled behind scenes
in a way that makes the waiting function hang?
(This is how I interpret your statement.)
I must say I seriously doubt that as it would mean a catastrophic design flaw of the synchronization mechanism of the operating system in my opinion.
Randor wrote: If you like I can create a sample application which continuously spawns/terminates a self deleting thread and then force a context switch before calling WaitForSingleObject. The alertable wait state will return 99% of the time and eventually deadlock.
If you are able to do that and wait on the thread handle before creating a new thread, I'd be delighted to see it.
I will even try and create such an abomination myself.
But if this is the case I don't see how any of our proposed solutions may prevent this deadlock.
Randor wrote: The cause of the deadlock will be a valid handle which is invalid in the context of the process calling WaitForSingleObject. I guess it would be better to use a different terminology as invalid seems to be confusing you.
Well, I wasn't confused until I read the underlined part above. But the confusion is more about what you mean rather than whether a handle is valid or invalid.
"It's supposed to be hard, otherwise anybody could do it!" - selfquote "High speed never compensates for wrong direction!" - unknown
|
|
|
|
|
Hi Roger,
Roger Stoltz wrote: Do you really mean that you have experienced a scenario where you have a handle that:
Let me clarify the scenario I am presenting:
1.) Engineer creates a CWinThread object with m_bAutoDelete set to TRUE.
2.) CWinThread is started.
3.) A context switch takes place in GUI thread.
4.) CWinThread completes and exits and the handle is dereferenced.
5.) GUI thread resumes from context switch.
6.) GUI calls WaitForSingleObject on the CWinThread->m_hThread with INFINITE.
7.) The handle is a valid handle, another object has been assigned this identifier.
8.) WaitForSingleObject never returns.
Yes, I have encountered this before in the real world. You can produce an application which exibits this handle recyling deadlock behavior.
Roger Stoltz wrote: I must say I seriously doubt that as it would mean a catastrophic design flaw of the synchronization mechanism of the operating system in my opinion.
I'm surprised that you have not read about this before. Its the same thing with window handles. I have noticed that you often reference Dr. Joseph Newcomer in your posts. What is occuring under the hood is essentially the same principles of the flaw described in Avoiding Multiple Instances of an Application[^] and window handles. Window handles can be closed and/or re-assigned to other windows. This can lead to deadlocks/race conditions. It is the essentially the same for thread/process handles. Handles cannot always be relied upon and they may be valid, invalid or re-assigned.
You can probably find other software engineers describing this flaw:
DuplicateHandle CWinThread Newcomer[^]
Best Wishes,
-David Delaune
|
|
|
|
|
|
Hi Roger,
Now I am uncertain if this was the problem Yuriy was having. I just read the entire thread again and noticed that in this post[^] Yuri states that "99% of cases the thread is already terminated, when the WaitForSingleObject() is called."
I am starting to think there may have been a serious design flaw. I guess we should have asked to see some code.
Anyway I am leaving the office soon.
Have a good night,
-David Delaune
|
|
|
|
|
Well, the OP's problem could still be the one we've been discussing.
There is a possibility that the handled gets recycled between thread termination and the call to ::WaitForSingleObject() . When he claims that the thread is already terminated in 99% of the cases I doubt he really checks the return value; the wait may have failed since the handle has been closed but he doesn't care because it means that the thread doesn't run any longer.
As I wrote earlier I still think he has introduced a race condition where the worker thread somehow sends a message to the main thread instead of posting. If the main thread has already assumed its waiting state on the thread handle the deadlock is a reality.
This is in my opinion the most common reason for deadlocks when it comes to multithreading and would most definitely result in the behaviour he has described.
It may be that he's calling a framework function that disguises the ::SendMessage() call.
The probability for a design flaw I guess is very close to 100%.
I will have a good night; it's almost 1:00AM in Sweden and I'm about to hit the sack.
I wish you a good night as well!
--
Rog
"It's supposed to be hard, otherwise anybody could do it!" - selfquote "High speed never compensates for wrong direction!" - unknown
|
|
|
|
|
You could create the thread in a suspended state, retrieve the thread handle then (before it's started executing) and store it way with the thread object pointer?
But you probably shouldn't do that anyway. I'd use MsgWaitForMultipleObjects[^] so I could both wait for the thread and dispatch window messages (you'll need to write your own message loop).
Java, Basic, who cares - it's all a bunch of tree-hugging hippy cr*p
|
|
|
|