Solved

Thread started with AfxBeginThread() hogging CPU

Posted on 2012-12-23
8
691 Views
Last Modified: 2012-12-28
I have CDialog based modal dialog that invokes a fairly lengthy processing step using the following call:

Thr=AfxBeginThread(MyFunction, pPam, THREAD_PRIORITY_LOWEST);

The thread starts up and runs nicely to completion.   However I have a CProgressCtrl on the invoking modal dialog that I want to update while the lengthy process is happening.

I have a timer set in the dialog that calls me every 100 ms.  At that time I attempt to set the progress bar using SetPos().  The problem I have is that I have to call Sleep() in the spawned thread in order to give the dialog a chance to update the progress bar.

I would have thought that the dialog would have gotten some cycles especially when I used  THREAD_PRIORITY_LOWEST for the spawned thread.

Is the main thread expected to get no cycles unless the spawned thread does some sleeping?

I'm running on a reasonable machine (Intel i5).
0
Comment
Question by:allanephillips
  • 4
  • 3
8 Comments
 
LVL 25

Expert Comment

by:Tony Giangreco
Comment Utility
Have you tried limiting the time alloted to the sleep command?
0
 

Author Comment

by:allanephillips
Comment Utility
Yes I have.  It seems as though I have to give it about 100 ms before things work.  That seems like a lot of time.
0
 
LVL 9

Expert Comment

by:Orcbighter
Comment Utility
Can you show some of the code in the MyFunction process?
0
 

Author Comment

by:allanephillips
Comment Utility
Here is the complete source.  It simply does symtax highlighting of some XML.  Of course it's fairly CPU intensive.


UINT __cdecl MyFunction(LPVOID pParam)
{
	Thread_t *pThread = (Thread_t *)pParam;

	pThread->lPos = 0;
	bool bReturn = MySyntaxHighlightFile(pThread->sInputName, pThread->sOutputName, &pThread->lPos);

	return 1;
}


// Copy the input file to the output file inserting RTF markup to syntax color the XML.
bool MySyntaxHighlightFile(const wchar_t *sInputFileName, const wchar_t *sOutputFileName, long *lPos)
{
	FILE *fpIn;
	_wfopen_s(&fpIn, sInputFileName, L"rb");
	if (!fpIn)
		return false;

	FILE *fpOut;
	_wfopen_s(&fpOut, sOutputFileName, L"wb");
	if (!fpIn)
		return false;
	char sTag[1000];
	iTagIndex = 0;
	sTag[0] = 0;

	long long i64FileLength = _filelengthi64(_fileno(fpIn));
	long long i64Step = (long long) ((i64FileLength / 60.0) + 0.5);
	long long i64CurPos = 0;

	bool bInTag = false;
	bool bInAttributes = false;
	bool bAttrValue = false;

	char sBOM[3];
	fread(sBOM, 1, 3, fpIn);				// Swallow the byte-order-mark.

	fputs("{\\rtf1{{\\colortbl ;"
			"\\red0\\greeen0\\blue0;"				// Regular text - black	= 1
			"\\red255\\green0\\blue0;"				// ObjectTag color		= 2
			"\\red0\\green128\\blue255;"			// Tag color			= 3
			"\\red0\\green0\\blue255;"				// Quote color			= 4
			"\\red30\\green150\\blue30;"			// Attribute name color	= 5
			"\\red0\\green0\\blue255;"				// Angle color			= 6
			"\\red192\\green192\\blue192;"			// Comment color		= 7
			"\\red0\\green128\\blue255;}"			// PI color				= 8
			, fpOut);

	unsigned iChar;
	while ((iChar = fgetc(fpIn)) != EOF)
	{
		i64CurPos++;
		switch (iChar)
		{
		case '\r':
			break;						// Don't need carriage returns.

		case '\n':
			fwrite("\\par ", 1, 5, fpOut);
			break;

		case '{':
		case '}':
		case '\\':
			fputc('\\', fpOut); 
			fputc(iChar, fpOut);
			break;

		case '<':
			{
				fputs("\\cf6 ", fpOut);
				fputc(iChar, fpOut);
				int iNextChar = fgetc(fpIn);
				i64CurPos++;
				switch (iNextChar)
				{
				case '!':
					fputs("\\cf7 ", fpOut);
					fputc(iNextChar, fpOut);
					break;

				case '?':
					fputs("\\cf8 ", fpOut);
					fputc(iNextChar, fpOut);
					break;

				case '/':
					fputc(iNextChar, fpOut);
					bInTag = true;
					iTagIndex = 0;
					break;

				default:
					bInTag = true;
					iTagIndex = 0;
					sTag[iTagIndex++] = iNextChar;
					sTag[iTagIndex] = 0;
				}
			}
			continue;

		case '>':
			if (bInTag)
			{
				OutputTag(sTag, fpOut);
				bInTag = false;
			}
			bInAttributes = false;
			fputs("\\cf6 ", fpOut);
			fputc(iChar, fpOut);
			fputs("\\cf1 ", fpOut);
			break;

		case ' ':
			if (bInTag)
			{
				OutputTag(sTag, fpOut);
				bInTag = false;
				bInAttributes = true;
			}
			fputc(iChar, fpOut);
			break;

		case '"':
			if (bInAttributes)
			{
				if (bAttrValue)
					fputs("\\cf4 \"\\cf5 ", fpOut);		// Closing quote for attribute value.
				else
					fputs("\\cf4 \"\\cf1 ", fpOut);		// Opening quote for attribute value.
				bAttrValue = !bAttrValue;
			}
			break;

		default:
			if (bInTag)
			{
				sTag[iTagIndex++] = iChar;
				sTag[iTagIndex] = 0;
			}
			else if (iChar <= 0x7F)
				fputc(iChar, fpOut);
			else
			{
				// Now we have to convert this UTF8 extended character to Unicode.
				unsigned char sUtf8[11];
				int iIndex = 0;
				sUtf8[iIndex++] = iChar;

				// Read in all the bytes of this unicode character.
				while ((iChar = fgetc(fpIn)) != EOF)
				{
					if ((iChar < 0x80) || (iChar > 0xBF) || (iIndex > 9))
						break;
					sUtf8[iIndex++] = iChar;
					i64CurPos++;
				}
				i64CurPos--;
				ungetc(iChar, fpIn);

				sUtf8[iIndex] = 0;
				wchar_t *sUnicode = ATW::UTF82Wide((char *)sUtf8);

				fprintf(fpOut, "\\u%d ?", *sUnicode);	// Extended character.
			}
		}
		if ((i64CurPos % i64Step) == 0)
			(*lPos)++;
	}

	fputs("}", fpOut);

	fclose(fpIn);
	fclose(fpOut);

	return true;
}

Open in new window

0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 
LVL 9

Expert Comment

by:Orcbighter
Comment Utility
Sorry, I meant the section of code where you call sleep, and the section of code where you pass information to update the progress bar.
0
 

Author Comment

by:allanephillips
Comment Utility
The code that updates the progress bar is simply:

    mProgressBar.StepIt();
    mProgressBar.UpdateWindow();

Open in new window


inside OnTimer().

The Sleep() call was at this point in the code I sent:

     if ((i64CurPos % i64Step) == 0)
      {
	  (*lPos)++;
          Sleep(100);
       }

Open in new window


This does actually work but 100 ms seems like a lot of time effectively doing nothing.
0
 
LVL 9

Accepted Solution

by:
Orcbighter earned 100 total points
Comment Utility
Okay, from what I can see and imply from the code you haven't supplied is this:
1. You start a thread to do some stuff which is compute-intensive, and seems to swallow up your CPU. Your timer events might be being queued as a result.
2. You have a timer that periodically calls progress.StepIt() to advance the visual display bar.
3. You found that you had to add a Sleep command to the compute-bound thread in order for the display update to get enough time to update the display, and that you had to increase the amount of time in the Sleep for it to work.

On point 1: Yes, without some kind of break in the thread process, it would consume CPU resources.
On point 3: My thoughts are that, if the timer event does not helpfully coincide with the Sleep command, it would not get enough time to act, thus you had to keep increasing the Sleep time in the thread, ie, the Sleep window in the background thread does not coincide with the window of the timer event.

Suggestions:
1. Change the Sleep command in the thread function back to 10 ms (the smallest effective amount of time you can get).
Now that the Sleep is so small, you can afford to sleep more times (more than i64CurPos % i64Step times). Thus your sleep will relinquish control for far shorter periods of time, but the increased frequency of the Sleep calls means other threads might get a look in.

2. If point 1 fixes the problem, good. If not, maybe consider another option rather than a timer.Instead of the timer, use a Windows Event and send that to an event handler in the dialog that updates the progress bar.
An additional thought is that the timer event that updates the Progress bar has no real link with the position of the file being processed. The time fires and just arbitrarily increments the progress bar. An event message might allow you a more connected link with the stepIt command by adding a parameter to the event message (but that might be version 2, yes ? :-) )
0
 

Author Closing Comment

by:allanephillips
Comment Utility
I'm accepting this even though I have not been able to make use of the information.  It feels as though threads are still useless on Windows so I've just dropped the separate thread.

When one spins off a thread with the priority set to "THREAD_PRIORITY_LOWEST" and the other thread(s) get no cycles without doing a call to Sleep() then it's obvious that threads have not been implemented in Windows in a way that's useful yet.
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

With most software applications trying to cater to multiple user needs nowadays, the focus is to make them as configurable as possible. For e.g., when creating Silverlight applications which will connect to WCF services, the service end point usuall…
For most people, the WrapPanel seems like a magic when they switch from WinForms to WPF. Most of us will think that the code that is used to write a control like that would be difficult. However, most of the work is done by the WPF engine, and the W…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA. http://www.experts-exchange.com/videos/1478/Excel-Error-Handlin…
You have products, that come in variants and want to set different prices for them? Watch this micro tutorial that describes how to configure prices for Magento super attributes. Assigning simple products to configurable: We assigned simple products…

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now