PDA

View Full Version : سوال: عمل نکردن کلیک بر روی دکمه هنگام اجرای برنامه



elahe1393
یک شنبه 17 اسفند 1393, 11:59 صبح
سلام
برنامه ای نوشتم که با دستگاهی از طریق پورت سریال در ارتباط است و قرار است بطور موازی یک سری داده را در کنار دیگر عملیات بخواند دکمه شروع و توقف دارد وقتی دکمه شروع را می زنم برنامه اجرا می شود حال می خواهم وقتی دکمه توقف را زدم برنامه متوقف شود و کار به پایان برسد ولی هنگام اجرا بعضی مواقع دکمه توقف با یک بار کلیک کار می کند ولی در بیشتر مواقع کار نمی کند و هر چه روی دکمه کلیک می کنم عمل نمی کند.

کد دکمه توقف

private void btnStop_Click(object sender, EventArgs e)
{
btnStart.Enabled = true;
btnStop.Enabled = false;
closed = true;
serialPort.Close();
}

کدهایی که باعث توقف فرایند موازی می شود

void CloseCnt()
{
Monitor.Enter(LockObj);
try
{
_CloseCnt();
}
catch { }
closed = true;
Monitor.Exit(LockObj);
}

void _CloseCnt()
{
while (endReapets == false && closed == false)
{
Monitor.Wait(LockObj);
Application.DoEvents();
}
}

می خوام موقع توقف پورت بسته بشه فرایند موازی خاتمه پیدا کنه تا باعث هیچ خطایی نشه نمی دونم مشکل کجاست لطفا راهنمایی کنید.

golbafan
یک شنبه 17 اسفند 1393, 12:18 عصر
سلام

serialPort.Close رو از داخل btnStop_Click برداشته و جای دیگری استفاده کنید (بعد از چک کردن closed == true)

در واقع هنگام کلیک فقط باید closed = true انجام بشه و در پروسه ارسال داده ها باید بعد از چک کردن این آیتم، پورت رو ببندید و null اش کنید:

serialPort.Close
serialPort = null

در ضمن حتما قبل از بستن پورت چک کنید که داده ها در حال ارسال هستند یا خیر...

void _CloseCnt()
{
while (endReapets == false && closed == false)
{
Monitor.Wait(LockObj);
Application.DoEvents();
}
serialPort.Close();
}

elahe1393
دوشنبه 18 اسفند 1393, 13:51 عصر
مرسی بابت کمک ولی الان مشکلم اینه که وقتی برنامه در حال اجراست نمیتونم روی دکمه توقف کلیک کنم یعنی عمل نمیکنه مثلا دیدید وقتی روی یه دکمه میری رنگش عوض میشه یا حاشیه دکمه رنگش عوض میشه میفهمی اگه کلیک کنی یه اتفاقی میفته الان این تغییر نمیکنه یعنی دکمه توقف هیچ عکس العملی حین اجرا نداره مثلا وقتی برنامه در حال اجراست هیچ مکثی نداره که بفهمه روی دکمه توقف کلیک شده من Application.DoEvents(); رو نوشتم تا این مکث اتفاق بیفته بفهمه ولی تاثیری نداشت راه حل چیه؟ چی رو باید چک کنم؟

golbafan
دوشنبه 18 اسفند 1393, 18:01 عصر
مرسی بابت کمک ولی الان مشکلم اینه که وقتی برنامه در حال اجراست نمیتونم روی دکمه توقف کلیک کنم یعنی عمل نمیکنه مثلا دیدید وقتی روی یه دکمه میری رنگش عوض میشه یا حاشیه دکمه رنگش عوض میشه میفهمی اگه کلیک کنی یه اتفاقی میفته الان این تغییر نمیکنه یعنی دکمه توقف هیچ عکس العملی حین اجرا نداره مثلا وقتی برنامه در حال اجراست هیچ مکثی نداره که بفهمه روی دکمه توقف کلیک شده من Application.DoEvents(); رو نوشتم تا این مکث اتفاق بیفته بفهمه ولی تاثیری نداشت راه حل چیه؟ چی رو باید چک کنم؟

سلام
این یعنی برنامه شما حین ارسال هنگ میکنه
بخاطر حلقه این اتفاق میوفته
شما بعد از هر بار ارسال در حلقه باید به برنامه استراحت بدی
در غیر این صورت باید کد ارسال دیتا رو در ترد بنویسی

elahe1393
سه شنبه 19 اسفند 1393, 09:54 صبح
سلام
این یعنی برنامه شما حین ارسال هنگ میکنه
بخاطر حلقه این اتفاق میوفته
شما بعد از هر بار ارسال در حلقه باید به برنامه استراحت بدی
در غیر این صورت باید کد ارسال دیتا رو در ترد بنویسی

من یکبار ابتدای اجرای برنامه ارسال انجام می دهم و در ادامه دریافت دیتا را از طریق ترد انجام می دهم من دائما بطور موازی دیتا از پورت دریافت می کنم یه تابعی هم در کدهای اصلی دارم که چک میکنه اگر مثلا closed = true شد یعنی کار به پایان رسیده پس دیگه نیاز به دریافت دیتا نداریم و پورت را هم می بندم پس ترد به همراه این تابع در حال اجراست حالا من کجا باید تغییر بدهم تا در موقع اجرا کلیک روی دکمه توقف اجرا شود؟

SabaSabouhi
سه شنبه 19 اسفند 1393, 12:40 عصر
من یکبار ابتدای اجرای برنامه ارسال انجام می دهم و در ادامه دریافت دیتا را از طریق ترد انجام می دهم من دائما بطور موازی دیتا از پورت دریافت می کنم یه تابعی هم در کدهای اصلی دارم که چک میکنه اگر مثلا closed = true شد یعنی کار به پایان رسیده پس دیگه نیاز به دریافت دیتا نداریم و پورت را هم می بندم پس ترد به همراه این تابع در حال اجراست حالا من کجا باید تغییر بدهم تا در موقع اجرا کلیک روی دکمه توقف اجرا شود؟

سلام
یه راه اینه که شما می‌تونی در اون thread یک static property داشته باشی که هر وقت روی دکمه‌ی Stop کلیک کردی، مقدارش رو عوض کنی و توی thread هم مرتب مقدار اون رو
چک کنی.
یه راه دیگه هم اینه که وقتی روی دکمه‌ی stop فشار دادی، کلاً اون thread رو ببنده.

صبا صبوحی

elahe1393
سه شنبه 19 اسفند 1393, 13:32 عصر
سلام
یه راه اینه که شما می‌تونی در اون thread یک static property داشته باشی که هر وقت روی دکمه‌ی Stop کلیک کردی، مقدارش رو عوض کنی و توی thread هم مرتب مقدار اون رو
چک کنی.
یه راه دیگه هم اینه که وقتی روی دکمه‌ی stop فشار دادی، کلاً اون thread رو ببنده.

صبا صبوحی

مرسی از راهنماییتون
مشکل اینجاست که اصلا مشخص نیست برنامه کلیک روی دکمه stop رو میفهمه یا نه؟ چون برنامه بقولی میره تو حالت هنگ که هیچ عملی رو درک نمیکنه تا زمانیکه به مرحله پایان کدهای اجراییش میرسه و کار دکمه شروع به پایان میرسه چطور میتونم برنامه رو از این هنگی دربیارم که کلیک روی دکمه رو بفهمه؟

SabaSabouhi
سه شنبه 19 اسفند 1393, 15:28 عصر
مرسی از راهنماییتون
مشکل اینجاست که اصلا مشخص نیست برنامه کلیک روی دکمه stop رو میفهمه یا نه؟ چون برنامه بقولی میره تو حالت هنگ که هیچ عملی رو درک نمیکنه تا زمانیکه به مرحله پایان کدهای اجراییش میرسه و کار دکمه شروع به پایان میرسه چطور میتونم برنامه رو از این هنگی دربیارم که کلیک روی دکمه رو بفهمه؟

سلام
اگه عملیات کنترل درگاه سریال در thread جداگانه انجام بشه، نباید این حالت پیش بیاد.
شما مطمئن هستی که thread اصلی رو به هیچ عنوان Wait نمی‌کنی؟

صبا صبوحی

elahe1393
چهارشنبه 20 اسفند 1393, 09:39 صبح
سلام
اگه عملیات کنترل درگاه سریال در thread جداگانه انجام بشه، نباید این حالت پیش بیاد.
شما مطمئن هستی که thread اصلی رو به هیچ عنوان Wait نمی‌کنی؟

صبا صبوحی

سلام
وقتی دکمه شروع برنامه کلیک میشه یه سری کد اجرا میشه، بعد تحت شرایط خاص پورت باز میشه، بعد یه دیتایی به پورت ارسال میشه، بعد thread خواندن از پورت، شروع به اجرا میکنه (این ترد وظیفه خواندن از پورت رو داره و دیتاهای رسیده رو تفکیک میکنه و روی نمودار رسم میکنه)، بعد تابع CloseCnt() فراخوانی میشه که وظیفه داره توسط یه حلقه چک کنه وقتی توی ترد خواندن به مرحله خاصی رسید و دیتای خاصی دریافت کرد که endReapets = true میشه کار رو به پایان برسونه، بعد پورت بسته میشه و فرایند کلیک بر روی دکمه شروع به پایان میرسه. برای اینکه متغیرها توی تردها به اشتراک گذاشته بشه و مشکلی حین فعالیت دو فرایند خواندن از پورت و برنامه اصلی بوجود نیاد من توی تابع CloseCnt از کد Monitor.Wait(LockObj); استفاده کردم که همون میشه توی ترد اصلی از wait استفاده کردم من از اول طراحی برنامه به مشکلات مختلف برخوردم که نهایت به این کدهای فعلی و نحوه پیاده سازی رسیدم و در حال حاضر برنامه به خوبی نیازهای منو برطرف میکنه تنها مشکلی که وجود داره همین دکمه توقف هست که برنامه زمانیکه من میخوام توقف کنه نمیکنه حالا راه حل مشکل من چیه لطفا راهنمایی کنید.

elahe1393
یک شنبه 24 اسفند 1393, 08:44 صبح
سلام چند روزی هست روی کد کار نکردم هنوز مشکل پا برجاست چطوری این مشکل رو رفع کنم لطفا راهنمایی نمایید.

SabaSabouhi
یک شنبه 24 اسفند 1393, 09:38 صبح
سلام
وقتی دکمه شروع برنامه کلیک میشه یه سری کد اجرا میشه، بعد تحت شرایط خاص پورت باز میشه، بعد یه دیتایی به پورت ارسال میشه، بعد thread خواندن از پورت، شروع به اجرا میکنه (این ترد وظیفه خواندن از پورت رو داره و دیتاهای رسیده رو تفکیک میکنه و روی نمودار رسم میکنه)، بعد تابع CloseCnt() فراخوانی میشه که وظیفه داره توسط یه حلقه چک کنه وقتی توی ترد خواندن به مرحله خاصی رسید و دیتای خاصی دریافت کرد که endReapets = true میشه کار رو به پایان برسونه، بعد پورت بسته میشه و فرایند کلیک بر روی دکمه شروع به پایان میرسه. برای اینکه متغیرها توی تردها به اشتراک گذاشته بشه و مشکلی حین فعالیت دو فرایند خواندن از پورت و برنامه اصلی بوجود نیاد من توی تابع CloseCnt از کد Monitor.Wait(LockObj); استفاده کردم که همون میشه توی ترد اصلی از wait استفاده کردم من از اول طراحی برنامه به مشکلات مختلف برخوردم که نهایت به این کدهای فعلی و نحوه پیاده سازی رسیدم و در حال حاضر برنامه به خوبی نیازهای منو برطرف میکنه تنها مشکلی که وجود داره همین دکمه توقف هست که برنامه زمانیکه من میخوام توقف کنه نمیکنه حالا راه حل مشکل من چیه لطفا راهنمایی کنید.

سلام
شاید من اشتباه می‌کنم، اما گمان می‌کنم نباید نیازی به Lock کردن داشته باشی. مگه «ترد»ی که از درگاه می‌خونه و «ترد» اصلی برنامه تو چه چیزی
ممکنه تداخل داشته باشن؟
و مطلب دیگه این که برای دریافت خبر از تمام شدن یک عمل چرا از حلقه استفاده می‌کنی؟ این که خیلی فشار به CPU میاره. یه راه‌کار دیگه پیدا کن.
اگه تو «ترد» اصلی نبود، می‌گفتم از EventWaitHandle استفاده کنی. خیلی بستگی داره که چه‌کاری می‌خوای انجام بدی.

صبا صبوحی

elahe1393
یک شنبه 24 اسفند 1393, 14:12 عصر
سلام
شاید من اشتباه می‌کنم، اما گمان می‌کنم نباید نیازی به Lock کردن داشته باشی. مگه «ترد»ی که از درگاه می‌خونه و «ترد» اصلی برنامه تو چه چیزی
ممکنه تداخل داشته باشن؟
و مطلب دیگه این که برای دریافت خبر از تمام شدن یک عمل چرا از حلقه استفاده می‌کنی؟ این که خیلی فشار به CPU میاره. یه راه‌کار دیگه پیدا کن.
اگه تو «ترد» اصلی نبود، می‌گفتم از EventWaitHandle استفاده کنی. خیلی بستگی داره که چه‌کاری می‌خوای انجام بدی.

صبا صبوحی

برای هماهنگی بین تردها این عمل رو انجام میدم چون قبل از این کار خطاهایی در برنامه ام رخ میداد که با lock کردن مشکلم حل شد
در مورد حلقه باید بگم، من تو دکمه شروع کدهایی رو نوشتم که پس از اجرای اون کدها ترد خوندن از پورت هم کار خودشو شروع میکنه، دیگه تو دکمه شروع کاری ندارم تا زمانیکه توی ترد خوندن به یه دیتای خاص برسم که دیگه کارم تموم بشه (تمام دیتاهای دریافتی برروی نمودار رسم میشه) برای اینکه ترد اصلی بسته نشه من از حلقه استفاده کردم تا وقتی اون دیتای خاص دریافت شد کار دکمه شروع به پایان برسه.
من الان همه کارهایی که میخواستم نرم افزار انجام بده رو بهش رسیدم فقط نمیتونم هر موقع میخوام بهش فرمان توقف بدم چیکار کنم؟