View Full Version : suspend کردن یک thread از داخل تابع نخ
soroush_vs
پنج شنبه 20 فروردین 1388, 15:17 عصر
با سلام
اگه ما یه نخ داشته باشیم و از داخل تابعش اون رو suspend کنیم آیا مشکلی بوجود میاد؟
من این کار رو میکنم ولی یه ارور پیش میاد و ویوژال استادیو وارد دیباگر میشه و این ارور رو میده
Unhandled exception at 0x00401ea7 in NFM.exe: 0xC0000005: Access violation reading location 0x0000002c.
Nima_NF
پنج شنبه 20 فروردین 1388, 18:41 عصر
SuspendThread در اصل برای ساخت برنامه های debug هست پس سعی کنید از آن اصلا استفاده نکنید. اگر قرا است این کار را انجام دهید راهی به کار گیرید که از بیرون از خود thread دیگری آن را با توابع همزمان سازی متوقف کند.
ضمنا کلا این کار خطرناک نیز هست، این بستگی به برنامه شما دارد، در اکثر موارد اگر از همزمان سازی ها استفاده کرده باشید و یا متغیر ها را به اشتراک گذاشته باشید این عمل در زمان نامناسب مشکلاتی ایجاد خواهد کرد.
soroush_vs
جمعه 21 فروردین 1388, 08:21 صبح
ممنونم آقا نیمای گل
نظرتون درمورد تابع API با اسم SuspendThread چی هست؟ آیا اون رو هم نمیشه از داخل خود نخ استفاده کرد؟
Nima_NF
جمعه 21 فروردین 1388, 18:26 عصر
در ارسال قبلی من دقیقا همین تابع SuspendThread را نام بردم که مواردی که گفتم توصیه های مایکروسافت بود و در کتاب ها هم به آن اشاره شده است. همواره از بیرون thread آن را کنترل کنید، حال متوقف کنید یا را اندازی کنید.
برای این کار از WaitForSingleObject و CreateEvent و غیره استفاده کنید که باید از بیرون کنترل شوند.
soroush_vs
جمعه 21 فروردین 1388, 19:28 عصر
آخه ما دو نمونه SuspendThread داریم یکی API هست و دیگری یک member function از کلاس CWinThread .
وقتی که دومی رو استفاده میکنم برنامه با ارور مواجه میشه ..همون اروری که در پست اول نوشتم.اما وقتی که از اولی استفاده میکنم این ارور به وجود نمیاد.
من فعلا از اولی استفاده کردم چون به شدت احتیاج دارم که از داخل نخ اجرای اون رو موقتا متوقف کنم .. یعنی حتما بلافاصله بعد از یه دستور خواص باید نخ رو suspend کنم .بنا به تجارب ارزشمند شما آیا راهی دارم که از داخل نخ این کار رو نکنم؟
Nima_NF
جمعه 21 فروردین 1388, 23:35 عصر
به خاطر داشته باشید وقتی از کلاس های MFC استفاده می کنید مانند CWinThread برای thread، آنگاه باید از توابع عضو همان کلاس استفاده کنید، مگر اینکه به شما گفته شده باشد که از win32 استفاده کنید. مثلا هرگز با MFC حافظه ای تخصیص ندهید و سپس با win32 آن را آزاد کنید. درست هست که بسیاری از عناوین توابع یکی هستند، اما ده ها متغیر و ماکرو دیگر برای معادل های آن ها در MFC در همان تابع مقداردهی می شوند تا یک محیط oop در اختیار شما باشد. پس اگر از SuspendThread عضو کلاس استفاده می کنید و خطا می دهد اشتباهی در کدهای شما وجود دارد، اما API کاری به کلاس های شما ندارد و این بدتر هست که خطا نمی دهد.
مثلا به شما اجازه داده شده است اگر از کلاس های MFC برای ساخت thread استفاده می کنید برای همزمان سازی ها از win32 برای کنترل استفاده کنید.
مثلا به این شکل در thread اصلی یک event بسازید:
CEvent* pEvent = new CEvent( FALSE, FALSE );
CWinThread* pThread;
pThread = ::AfxBeginThread( ThreadProc, pEvent, 0, 0, 0, NULL);
pEvent->SetEvent(); // means threas is on (signaled)
در هر جایی که می خواهید 2 thread متوقف شود آن را Reset کنید:
pEvent->ResetEvent(); // means thread must suspend
و مثلا thread 2 َما کد زیر می تواند داشته باشد؛ تابع WaitForSingleObject در صورتی که ResetEvent کرده باشید باعث suspend شدن آن می شود و تا فراخوانی مجدد SetEvent مقداری بر نمی گرداند:
UINT __cdecl ThreadProc( LPVOID lpParameter )
{
CEvent* pEvent = (CEvent*)( lpParameter );
VERIFY( pEvent != NULL );
while (1 )
{
::WaitForSingleObject( pEvent->m_hObject, INFINITE );
// Do something here
}
}
از طریق گوگل در فروم جستجو کنید مثال های دیگری نیز گفته ام.
soroush_vs
یک شنبه 23 فروردین 1388, 11:11 صبح
این حلقه ی while کارایی برنامه رو پایین نمی آره؟ یا سی پی رو رو مشغول نمیکنه؟
آیا نمیشه تابع WaitForSingleObject رو بجای اینکه در یک حلقه قرار بدیم آیا نمیشه فقط یک بار فراخوانی کرد؟
علت اینکه در حلقه گذاشتید چیه؟
آخرین سوال اینکه چرا ::WaitForSingleObject این دستور رو با دو colon گذاشتید؟ ::
Nima_NF
یک شنبه 23 فروردین 1388, 16:30 عصر
- تابع WaitForSingleObject با توابع معمولی فرق دارد، زمانی مقدار بر می گرداند که در حالت signaled باشد یعنی پیام برایش ارسال کرده باشید، در غیر این صورت در همان خط منتظر می ماند تا از ویندوز توسط event ها برایش پیام ارسال شود. پس این طور فکر نکنید که حلقه while همیشه اجرا می شود. تمامی برنامه های ویندوز (خصوصا thread 1) در قسمت پردازش پیام ها در یک حلقه بی نهایت هستند.
- حلقه while ضروری نیست، اگر برنامه شما در thread 2 فقط باید یکسری کد را اجرا کند و سپس تمام شود به while نیاز نیست. فقط یک مثال بود برای اینکه هرگاه پیام فرستاده شده درست قبل از اجرا بعدی در زمانی مناسب thread به حالت suspend برود.
- پس اگر قرار هست یک بار برنامه suspend شود حلقه نیاز نیست، در هر جایی که خواستید WaitForSingleObject را یک بار فراخوانی کنید. مثلا:
UINT __cdecl ThreadProc( LPVOID lpParameter )
{
CEvent* pEvent = (CEvent*)( lpParameter );
VERIFY( pEvent != NULL );
if ( x == 10 )
::WaitForSingleObject( pEvent->m_hObject, INFINITE );
else
// Do something else
}
- دوکلون :: برای این هست که در MFC بگوییم اگر تابع مشابهی در کتابخانه های MFC وجود دارد آن را استفاده نکن و معادل win32 API را اجرا کن.
vBulletin® v4.2.5, Copyright ©2000-1404, Jelsoft Enterprises Ltd.