PDA

View Full Version : سوال: چگونگی اضافه کردن یه thread جدید بین دو تا thread اصلی و فرعی برای انجام کاری خاص بدون تداخل



elahe1393
سه شنبه 20 آبان 1393, 13:27 عصر
در ادامه این سوال (http://barnamenevis.org/showthread.php?473787-%D8%A8%D8%A7%D8%B2-%D9%88-%D8%A8%D8%B3%D8%AA%D9%87-%DA%A9%D8%B1%D8%AF%D9%86-thread-%D8%A7%DB%8C%D8%AC%D8%A7%D8%AF-%D8%B4%D8%AF%D9%87)که مشکلم حل شد
نیازهای برنامه ام عوض شده براساس اینکه یه دستگاه دارم که دو تا بازو داره با پورت سریال باهاش در ارتباطم تنظیم میکنم که کدوم بازو فعال باشه و چندتا تکرار حرکت داشته باشه اگر یه بازو فعال باشه نمودار تغییر زاویه و سرعت مربوط به اون بازو در picturebox مربوط به اون بازو رسم میشه این زاویه و سرعت بازو از یه thread فرعی که موازی برنامه اصلی داره اجرا میشه تامین میشه هر بار که حرکت تکرار میشه یه نمودار جدید به picturebox مربوطه اضافه میشه پایان هر تکرارم از اونجایی مشخص میشه که من یه بار بازو رو در جهت حرکت تکون میدم بعد برمیگردم دوباره که میخوام در جهت حرکت ، حرکت کنم تکرار تموم میشه و میره تکرار بعدی یعنی اینجوری رسم بشه
125538
حالا مشکل من اونجاییه که وقتی دو تا بازو فعال باشه من مثلا تعیین میکنم 3 بار تکرار انجام بشه هر بازو باید مجزا سه بار حرکت کنه نمودارش تو picturebox مربوط به خودش رسم بشه و پایان تکرار خاص خودشو داره این رسم هم باید همزمان برای هر دو بازو انجام بشه(چه دو بازو همزمان حرکت کنن چه ناهمزمان) پس من نیاز دارم برای رسم نمودار دو بازو همزمان کاری کنم یه سری کد دوبار همزمان البته با مقادیر متفاوت اجرا بشه پس نیاز به یه ترد جدید دارم وقتی میخوام مثلا بازوی راست رو تو thread اصلیم رسم کنم که داره داده هاشو از thread فرعی میگیره نیاز دارم همزمان یه thread دیگه هم ایجاد کنم که همین کار رو روی بازو چپ انجام بده داده هاشو از thread فرعی بگیره رسم کنه
الان مشکل اصلیم اینه که این کار انجام میشه ولی نتایجم کمی غیرمنطقیه و اینکه یه تاخیری در رسم وجود داره و اینکه میخوام مثلا حلقه تکرارم یه بار انجام بشه ولی وقتی حلقه تموم میشه دوباره اجرا میشه
لطفا راهنمایی کنید آیا روشم درسته چیکار باید بکنم

delegate void Fesfunc();
Fesfunc threadRead;
delegate void Fesfunc1();
Fesfunc1 threadDrawRightChart;
private object LockObj = new object();
private bool start = false, closed = true, endReapet = false;

private void btnStart_Click(object sender, EventArgs e)
{
یه سری کد

start = true;

Fesfunc fescommand = new Fesfunc(Fescommand);
threadRead = new Fesfunc(Fescommand);
threadRead.BeginInvoke(null, null);

یه سری کد

if (lblLeftIsEnable.Text == "بازوی چپ فعال است" && lblRightIsEnable.Text == "بازوی راست فعال است")
{
leftRightEnable = true;
}

یه سری کد

if (leftRightEnable == true)
{
Fesfunc1 drawRightChart = new Fesfunc1(DrawRightChart);
threadDrawRightChart = new Fesfunc1(DrawRightChart);
threadDrawRightChart.BeginInvoke(null, null);

for (int i = 1; i <= int.Parse(lblReapetValue.Text); i++)
{
Start();
endReapet = false;

یه سری کد برای عملیات مربوط به بازوی چپ و رسم نمودار زمینه چارت
CloseCnt();
}
}
else
{
if (lblLeftIsEnable.Text == "بازوی چپ فعال است")
{
for (int i = 1; i <= int.Parse(lblReapetValue.Text); i++)
{
Start();
endReapet = false;

یه سری کد برای عملیات مربوط به بازوی چپ و رسم نمودار زمینه چارت
CloseCnt();
}
}
else if (lblRightIsEnable.Text == "بازوی راست فعال است")
{
for (int i = 1; i <= int.Parse(lblReapetValue.Text); i++)
{
Start();
endReapet = false;

یه سری کد برای عملیات مربوط به بازوی راست و رسم نمودار زمینه چارت
CloseCnt();
}
}
یه سری کد
}

private void DrawRightChart()
{
Monitor.Enter(LockObj);
try
{
_DrawRightChart();
}
catch { }
Monitor.Exit(LockObj);
}

private void _DrawRightChart()
{

یه سری کد
for (int i = 1; i <= int.Parse(lblReapetValue.Text); i++)
{
Start();
endReapet = false;

یه سری کد برای عملیات مربوط به بازوی راست و رسم نمودار زمینه چارت

CloseCnt();

}

}

private void Fescommand()
{
while (true)
{
if (!Monitor.TryEnter(LockObj, 100))
continue;
if (closed)
Monitor.Wait(LockObj);
try
{
_Fescommand();
}
catch { }
Monitor.Exit(LockObj);
}

private void _Fescommand()
{
try
{
if (start)
{
یه سری کد برای تفکیک اطلاعات دریافتی
یه سری کد برای رسم خط سرعت در زاویه
یه سری کد برای بررسی پایان تکرار حرکت
if (شرط)
{
endReapet = true;
یه سری کد
}
}
Monitor.PulseAll(LockObj);
}
catch (Exception e)
{
MessageBox.Show("" + e.Message);
}
}

void Start()
{
Monitor.Enter(LockObj);
try
{
_Start();
}
catch { }
Monitor.Exit(LockObj);
}

void _Start()
{
closed = false;
Monitor.PulseAll(LockObj);
}

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

void _CloseCnt()
{
while (endReapet == false)
{
Monitor.Wait(LockObj);
}
}

elahe1393
یک شنبه 25 آبان 1393, 10:40 صبح
هیچ کس که به من تو این مرحله کمک نکرد راه و روشمو عوض کردم دیگه از thread اضافه استفاده نکردم اومدم تو همون thread که عمل خوندن رو انجام میده بررسی پایان تکرار رو قرار دادم به نتیجه دلخواه رسیدم ولی یه مشکل دارم اینکه رسم نمودارم تاخیر داره وقتی تمرین رو شروع میکنم و بازو هارو حرکت میدم تا زمانیکه روی نمودار زاویه و سرعت رو نشون بده به اندازه 2 ثانیه تاخیر وجود داره همه چی همون جور هست که میخوام ولی نمیدونم این تاخیر مربوط به چه بخشی میشه آیا مربوط به بافر پورتم هست یا مربوط به کدهایی که نوشتم و اینکه کدهام چندتا تابع تو در تو هست این منجر به تاخیر میشه ولی وقتی تایمر میذارم خوندن دیتام و رسمش خیلی کوتاهه حتی به میلی ثانیه هم نمیرسه

مجدد کدهایی که مربوط به این بخش بود رو در زیر قرار میدم امیدوارم یکی یه کمکی بکنه

delegate void Fesfunc();
Fesfunc threadRead;
private object LockObj = new object();
private bool start = false, closed = true, endReapet = false;

private void btnStart_Click(object sender, EventArgs e)
{
یه سری کد

start = true;

Fesfunc fescommand = new Fesfunc(Fescommand);
threadRead = new Fesfunc(Fescommand);
threadRead.BeginInvoke(null, null);

یه سری کد

if (lblLeftIsEnable.Text == "بازوی چپ فعال است" && lblRightIsEnable.Text == "بازوی راست فعال است")
{
leftRightEnable = true;
}

یه سری کد

Start();
if (leftRightEnable == true)
{
list = chart.DrawCharts(bitmapLeft, modelGraphicLeft, int.Parse(leftStartPoint), int.Parse(leftEndPoint), bitmapRight, modelGraphicRight, int.Parse(rightStartPoint), int.Parse(rightEndPoint), 1);
pbxLeft.Image = list[0];
pbxRight.Image = list[1];
reapetID = Guid.NewGuid();
db.InsertDataReapet(reapetID.ToString(), deviceID, reportID.ToString(), leftRightEnable, reapetNumber);
}
else
{
if (lblLeftIsEnable.Text == "بازوی چپ فعال است")
{
sid = "Left";
reapetID = Guid.NewGuid();
bitmap = chart.DrawChart("Left", bitmapLeft, modelGraphicLeft, 1, int.Parse(leftStartPoint), int.Parse(leftEndPoint));
pbxLeft.Image = bitmap;
db.InsertDataReapet(reapetID.ToString(), deviceID, reportID.ToString(), leftRightEnable, reapetNumber);

}
else if (lblRightIsEnable.Text == "بازوی راست فعال است")
{
sid = "Right";
reapetID = Guid.NewGuid();
bitmap = chart.DrawChart("Right", bitmapRight, modelGraphicRight, 1, int.Parse(rightStartPoint), int.Parse(rightEndPoint));
pbxRight.Image = bitmap;
db.InsertDataReapet(reapetID.ToString(), deviceID, reportID.ToString(), leftRightEnable, reapetNumber);
}
}
CloseCnt();
db.UpdateReport(reportID.ToString(), timeDate.Time());
}
یه سری کد
}


private void Fescommand()
{
while (true)
{
if (!Monitor.TryEnter(LockObj, 100))
continue;
if (closed)
Monitor.Wait(LockObj);
try
{
_Fescommand();
}
catch { }
Monitor.Exit(LockObj);
}

private void _Fescommand()
{
try
{
if (start)
{
if (leftRightEnableForDraw)
{
while ((countLeft <= reapetNumber && countRight <= reapetNumber) || (countLeft <= reapetNumber && countRight > reapetNumber) || (countLeft > reapetNumber && countRight <= reapetNumber))
{
SplitData(); برای تفکیک سازی بسته داده ای که از پورت سریال میرسه
if (leftEndPoint != null && recievedData.LeftPoint != null && rightEndPoint != null && recievedData.RightPoint != null)
{
DrawPoint(sid, leftRightEnableForDraw, recievedData, bitmapLeft, modelGraphicLeft, bitmapRight, modelGraphicRight); برای رسم نقطه بر روی چارت که باپارامتر leftRightEnableForDraw مشخص می شود که هر دو بازو فعال هست یا فقط یه بازو که عملیات مربوط انجام شود

endLeftReapet = EndLeftReapet();تعیین کننده اینکه ایا تکرار تموم شده
if (endLeftReapet == true)
{
countLeft++;
if (countLeft <= reapetNumber)
{
reapetID = Guid.NewGuid();
bitmapLeft = chart.DrawChart("Left", bitmapLeft, modelGraphicLeft, countLeft, int.Parse(leftStartPoint), int.Parse(leftEndPoint));
pbxLeft.Image = bitmapLeft;
db.InsertDataReapet(reapetID.ToString(), deviceID, reportID.ToString(), false, reapetNumber);
}
}

endRightReapet = EndRightReapet();
if (endRightReapet == true)
{
countRight++;
if (countRight <= reapetNumber)
{
reapetID = Guid.NewGuid();
bitmapRight = chart.DrawChart("Right", bitmapRight, modelGraphicRight, countRight, int.Parse(rightStartPoint), int.Parse(rightEndPoint));
pbxRight.Image = bitmapRight;
db.InsertDataReapet(reapetID.ToString(), deviceID, reportID.ToString(), true, reapetNumber);
}
}
}
leftPreviousStatus = leftStatus;
rightPreviousStatus = rightStatus;
Monitor.PulseAll(LockObj);
}
}
else
{
if (sid == "Left")
{
while (countLeft <= reapetNumber)
{
SplitData();
if (leftEndPoint != null && recievedData.LeftPoint != null)
{
DrawPoint(sid, leftRightEnableForDraw, recievedData, bitmapLeft, modelGraphicLeft, bitmapRight, modelGraphicRight);

endLeftReapet = EndLeftReapet();
if (endLeftReapet == true)
{
countLeft++;
if (countLeft <= reapetNumber)
{
reapetID = Guid.NewGuid();
bitmapLeft = chart.DrawChart("Left", bitmapLeft, modelGraphicLeft, countLeft, int.Parse(leftStartPoint), int.Parse(leftEndPoint));
pbxLeft.Image = bitmapLeft;
db.InsertDataReapet(reapetID.ToString(), deviceID, reportID.ToString(), false, reapetNumber);
}
}
}
leftPreviousStatus = leftStatus;
Monitor.PulseAll(LockObj);
}
}
else
{
while (countRight <= reapetNumber)
{
SplitData();
if (rightEndPoint != null && recievedData.RightPoint != null)
{
DrawPoint(sid, leftRightEnableForDraw, recievedData, bitmapLeft, modelGraphicLeft, bitmapRight, modelGraphicRight);

endRightReapet = EndRightReapet();
if (endRightReapet == true)
{
countRight++;
if (countRight <= reapetNumber)
{
reapetID = Guid.NewGuid();
bitmapRight = chart.DrawChart("Right", bitmapRight, modelGraphicRight, countRight, int.Parse(rightStartPoint), int.Parse(rightEndPoint));
pbxRight.Image = bitmapRight;
db.InsertDataReapet(reapetID.ToString(), deviceID, reportID.ToString(), true, reapetNumber);
}
}
}
rightPreviousStatus = rightStatus;
Monitor.PulseAll(LockObj);
}
}
}

endReapets = true;
}
}
catch (Exception e)
{
MessageBox.Show("" + e.Message);
}
}

private void SplitData()
{
try
{
endLeftReapet = false;
endRightReapet = false;
string str = ReceiveData();

string[] recieveDataPack = str.Split(new char[] { '$', ',', '#' }, StringSplitOptions.RemoveEmptyEntries);

if (recieveDataPack.Length == 8)
{
recievedData.LeftHardnessLevel = int.Parse(recieveDataPack[4]);
recievedData.LeftSpeed = (-1) * int.Parse(recieveDataPack[5]);
if (recievedData.LeftSpeed < 0)
{
lblSpeedLeftValue.Text = ((-1) * recievedData.LeftSpeed).ToString();
}
else
{
lblSpeedLeftValue.Text = recievedData.LeftSpeed.ToString();
}
recievedData.LeftPoint = ((-1) * (int.Parse(recieveDataPack[6]) * 360) / 800).ToString();
lblPointLeftValue.Text = recievedData.LeftPoint;
recievedData.RightHardnessLevel = int.Parse(recieveDataPack[1]);
recievedData.RightSpeed = int.Parse(recieveDataPack[2]);
if (recievedData.RightSpeed < 0)
{
lblSpeedRightValue.Text = ((-1) * recievedData.RightSpeed).ToString();
}
else
{
lblSpeedRightValue.Text = recievedData.RightSpeed.ToString();
}
recievedData.RightPoint = ((int.Parse(recieveDataPack[3]) * 360) / 800).ToString();
lblPointRightValue.Text = recievedData.RightPoint;
count++;
if (count == 15)
{
serialPort.DiscardOutBuffer(); بین رسم نمودارم فاصله میفتاد میفهمیدم بسته ها ناقصه برای اینکه بسته ناقصم درست بشه اینکارو کردم نمیدونم درسته یا نه!
count = 0;
}
}
}
catch (Exception e)
{
MessageBox.Show("" + e.Message);
}
}

public void DrawPoint(string sid, Boolean leftRightEnableForDraw, pointSpeed point, Bitmap bitmapLeft, Graphics modelGraphicLeft, Bitmap bitmapRight, Graphics modelGraphicRight)
{
db.InsertSpeedData(reapetID.ToString(), int.Parse(point.LeftPoint), point.LeftSpeed, int.Parse(point.RightPoint), point.RightSpeed);

float radLeft = (float)(Math.PI * int.Parse(point.LeftPoint) / 180);
float xLeft = 100 * (float)Math.Abs(Math.Cos(radLeft)), yLeft = bitmapLeft.Height - 100 * (float)Math.Abs(Math.Sin(radLeft));
float xxLeft = (100 + 3 * point.LeftSpeed) * (float)Math.Abs(Math.Cos(radLeft)), yyLeft = bitmapLeft.Height - (100 + 3 * point.LeftSpeed) * (float)Math.Abs(Math.Sin(radLeft));
float radRight = (float)(Math.PI * int.Parse(point.RightPoint) / 180);
float xRight = 100 * (float)Math.Abs(Math.Cos(radRight)), yRight = bitmapRight.Height - 100 * (float)Math.Abs(Math.Sin(radRight));
float xxRight = (100 + 3 * point.RightSpeed) * (float)Math.Abs(Math.Cos(radRight)), yyRight = bitmapRight.Height - (100 + 3 * point.RightSpeed) * (float)Math.Abs(Math.Sin(radRight));

if (leftRightEnableForDraw == true)
{
if (countLeft <= reapetNumber)
SwitchLeftReapet(point, xLeft, xxLeft, yLeft, yyLeft, countLeft); برای رسم نقطه روی نمودار مربوط به خودش
if (countRight <= reapetNumber)
SwitchRightReapet(point, xRight, xxRight, yRight, yyRight, countRight);
pbxLeft.Refresh();
pbxRight.Refresh();
}
else
{
if (sid == "Left")
{
SwitchLeftReapet(point, xLeft, xxLeft, yLeft, yyLeft, countLeft);
pbxLeft.Refresh();
}
else
{
SwitchRightReapet(point, xRight, xxRight, yRight, yyRight, countRight);
pbxRight.Refresh();
}
}
}

void Start()
{
Monitor.Enter(LockObj);
try
{
_Start();
}
catch { }
Monitor.Exit(LockObj);
}

void _Start()
{
closed = false;
Monitor.PulseAll(LockObj);
}

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

void _CloseCnt()
{
while (endReapet == false)
{
Monitor.Wait(LockObj);
}
}

elahe1393
یک شنبه 25 آبان 1393, 10:49 صبح
راستی گاهی وقتی دوتا بازو فعال باشند این خطارو هم میده مربوط به چیه راه حلش چیه؟
125755

elahe1393
یک شنبه 25 آبان 1393, 14:39 عصر
کسی نیست مرا یاری کند
الان تو thread خوندن از پورت تایمر گذاشتم قبل اینکه دیتا گرفته بشه مثلا میلی ثانیه برابر 456 هست بعد دریافت دیتا و تفکیک کردنش میلی ثانیه برابر 458 هست بعد از رسم نقطه و چک کردن اینکه به پایان تکرار رسیدیم یا نه میلی ثانیه برابر 493 هست یعنی هنگام ورود به thread برابر 456 هنگام خروج 493 و این ترد هی اجرا میشه آیا این زمان باعث تاخیر ارسال دیتا و خوندن و رسمش میشه که روند از همزمانی ارسال دیتا توسط دستگاه و رسمش روی نمودار درمیاد برای اینکه من همزمانی بین ارسال دیتا از دستگاه و دریافت دیتا توسط برنامه داشته باشم باید از serialport.DiscardOutBuffer() استفاده کنم؟ خطای بالا دلیلش چیه؟

elahe1393
دوشنبه 26 آبان 1393, 10:55 صبح
خواهشا یکی یه کمکی بکنه الان وقتی برنامه شروع به کار میکنه با تاخیر چندثانیه ای نمودار رسم میشه بعد منحنی مربوط به تکرار اول هم رسم نمیشه مشکلم کجاست؟