Link to home
Start Free TrialLog in
Avatar of allanephillips
allanephillipsFlag for Canada

asked on

Thread started with AfxBeginThread() hogging CPU

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).
Avatar of Tony Giangreco
Tony Giangreco
Flag of United States of America image

Have you tried limiting the time alloted to the sleep command?
Avatar of allanephillips

ASKER

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.
Can you show some of the code in the MyFunction process?
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

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.
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.
ASKER CERTIFIED SOLUTION
Avatar of Orcbighter
Orcbighter
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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.