Solved

Thread started with AfxBeginThread() hogging CPU

Posted on 2012-12-23
8
743 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
8 Comments
 
LVL 25

Expert Comment

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

Author Comment

by:allanephillips
ID: 38717187
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
ID: 38721753
Can you show some of the code in the MyFunction process?
0
Online Training Solution

Drastically shorten your training time with WalkMe's advanced online training solution that Guides your trainees to action. Forget about retraining and skyrocket knowledge retention rates.

 

Author Comment

by:allanephillips
ID: 38721907
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
 
LVL 9

Expert Comment

by:Orcbighter
ID: 38722778
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
ID: 38723503
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
ID: 38726408
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
ID: 38727305
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

Instantly Create Instructional Tutorials

Contextual Guidance at the moment of need helps your employees adopt to new software or processes instantly. Boost knowledge retention and employee engagement step-by-step with one easy solution.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

zlib is a free compression library (a DLL) on which the popular gzip utility is built.  In this article, we'll see how to use the zlib functions to compress and decompress data in memory; that is, without needing to use a temporary file.  We'll be c…
Whether you've completed a degree in computer sciences or you're a self-taught programmer, writing your first lines of code in the real world is always a challenge. Here are some of the most common pitfalls for new programmers.
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…
I've attached the XLSM Excel spreadsheet I used in the video and also text files containing the macros used below. https://filedb.experts-exchange.com/incoming/2017/03_w12/1151775/Permutations.txt https://filedb.experts-exchange.com/incoming/201…

738 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