PDA

View Full Version : حرفه ای: مشکل نمایش و چاپ متن در یک Label با Thread



M.KH-SH
پنج شنبه 17 مرداد 1392, 20:34 عصر
سلام و خسته نباشید خدمت اساتید گرامی

یک سئوال داشتم

یک تابع رو با Thread فراخوانی می کنم و اونو Start میکنم

sc = new Thread(new ThreadStart(xx));
sc.Start();

در تابع xx فرامینی هست که به تابع Event مورد نظرم در کامپوننت ارسال میکنم و در فرمی که از کامپوننت استفاده میکنم میخوام این رویداد زمانی که فراخوانی میشه مقدار دریافتی رو به چاپ برسونه حالا مشکل اینجاست که میگه::::

Cross-thread operation not valid: Control 'Form1' accessed from a thread other than the thread it was created on.

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


کل کدهای من در یک کلاس جداگانه نوشته شده و از اون کلاس فراخوانی میشه با Event ها.


ممنون میشم راهنمایی کنین تا مشکل من حل بشه.

mousa1992
پنج شنبه 17 مرداد 1392, 20:42 عصر
در حالت معمول شما نمیتونید از ترد دیگه ای به ترد اصلی دسترسی داشته باشید - برا انجام این کار باید از delegate ها استفاده کنید و یا اینکه از کامپوننت BackGroundWorker استفاده کن که خیلی راحته و جز کامپوننت های خود ویژوال هست

موفق باشی

Direlap
جمعه 18 مرداد 1392, 00:12 صبح
من خودم همین مشکل رو داشتم که اینطوری کمکم کردن :

http://barnamenevis.org/showthread.php?364002-%D9%87%D9%86%DA%AF-%DA%A9%D8%B1%D8%AF%D9%86-%D9%81%D8%B1%D9%85-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87&p=1606909&viewfull=1#post1606909

M.KH-SH
جمعه 18 مرداد 1392, 01:23 صبح
در حالت معمول شما نمیتونید از ترد دیگه ای به ترد اصلی دسترسی داشته باشید - برا انجام این کار باید از delegate ها استفاده کنید و یا اینکه از کامپوننت BackGroundWorker استفاده کن که خیلی راحته و جز کامپوننت های خود ویژوال هست

موفق باشی

دوست خوبه من سیستم کلی ترد رو میدونم چیه میخوام در حالت طراحی برنامه از ترد استفاده کنم و نتیجه رو ببینم لطفا در این باره راهنمایی بفرمایید.

M.KH-SH
جمعه 18 مرداد 1392, 01:31 صبح
من خودم همین مشکل رو داشتم که اینطوری کمکم کردن :

http://barnamenevis.org/showthread.p...=1#post1606909 (http://barnamenevis.org/showthread.php?364002-%D9%87%D9%86%DA%AF-%DA%A9%D8%B1%D8%AF%D9%86-%D9%81%D8%B1%D9%85-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87&p=1606909&viewfull=1#post1606909)

ممنونم ولی توجه داشته باش که::::

دارم یک کلاس طراحی میکنم برای انجام دادن یک عملیات خاص که از هیچ جا ارث نبرده و خودش مادر هست در این کلاس چندین delegate void وجود داره و در کلاس با استفاده از delegate ها event های طراحی شده در این کلاس یک تابع وجود داره که با کد بالا با استفاده از thread فراخوانی میشه در این تابع یک حلقه while هم قرار داده شده که عملیات رو انجام میده و جواب رو event مربوطه ارسال میکنه که در برنامه زمانی از این کلاس نمونه ساختم در رویداد مورد نظر از دریافتی کلاس استفاده کنم.

خوب زمانی که میخوام از ورودی این رویداد استفاده کنم خطا میده که خطا رو شما میگین با this.Invoke و this.BeginInvoke رفع کنم ولی این پاسخ من نبود چون هیچ کدوم از این 2 روش جواب گویی نداشته بعد هم نیاز هست که این دستورات در کلاس اصلی قرار بگیره و اطلاعات جوری ارسال بشه که نیاز به استفاده کردن از Invoke و BeginInvoke در برنامه نباشه و خیلی راحت از خود اطلاعات استفاده کرد

این نکته هم بگم که ترد تنها در زمان نمایش برنامه در حالت کد نویسی خطا میده ولی زمان اجرا مستقیم فایل exe هیچ خطایی وجود نداره و همه چی درست کار میکنه.

M.KH-SH
جمعه 18 مرداد 1392, 01:38 صبح
در واقع نیاز دارم یک جواز بدم تا بشه از ترد جانبی در ترد اصلی استفاده کرد و به هم انتقال داده داشته باشن

mousa1992
جمعه 18 مرداد 1392, 01:41 صبح
ببین عزیز من شما متن خطایی که بهتون میده رو بخون بینم چی میگه ؟
داره میگه ی تردی که کلاس form1 توی اون ساخته نشده میخواد درسترسی پیدا کنه بهش
شما به درستی از ترد ها استفاده نکردید و فقط کافیه 5 دقیقه وقتتون رو بذارید و در مورد backgroundworker مطالعه کنید چون چیز خاصی نداره و تو همین سایت مطالب بسیار زیادی در موردش هست

M.KH-SH
جمعه 18 مرداد 1392, 01:45 صبح
پیشنهاد شما چیه؟
اینه که من تابع رو در کلاسم تغییر بدم از BackgroundWorker استفاده کنم و دستورات رو به event مربوطه ارسال کنم؟

mousa1992
جمعه 18 مرداد 1392, 01:50 صبح
شما توی کامپوننتتون ی سری رویداد رو تعریف کردین درسته ؟ و با استفاده از تردی توی کامپوننت دارید تابعی رو اجرا میکنید که این تابع با اجرا شدنش میاد رویداد شما رو فراخوانی میکنه و پارامترهایی رو بهش ارسال میکنه و از اون طرف توی فرمتون با raise شدن رویداد مقادیر این ارگومانها رو میخواید بخونین درسته ؟

M.KH-SH
جمعه 18 مرداد 1392, 01:55 صبح
الان با BackgroundWorker این کار رو انجام دادم بازم خطا رو دیدم همون خطا هستش.

M.KH-SH
جمعه 18 مرداد 1392, 02:01 صبح
این کلاس مشابه

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace MKHSH.Windows.Control
{
public delegate void eventHandle(object sender, object e);

public partial class Component1 : Component
{
public event eventHandle even;
Thread sc;
public Component1()
{
if (LicenseManager.UsageMode == LicenseUsageMode.Runtime)
{
//BackgroundWorker bc = new BackgroundWorker();
//bc.DoWork += bc_DoWork;
//bc.RunWorkerAsync();
//check = true;
sc = new Thread(new ThreadStart(xx));
sc.IsBackground = true;
sc.Start();
}
}

void bc_DoWork(object sender, DoWorkEventArgs e)
{
while (true)
{
Oneven(DateTime.Now.ToString());
// Oneven("");
}
}


public bool check { get; set; }

protected virtual void Oneven(object e)
{

if (e != null)
even(this, e);
}

private void xx()
{
while (true)
{
Oneven(DateTime.Now.ToString());
}
}


}
}

mousa1992
جمعه 18 مرداد 1392, 02:04 صبح
backgroundworker سه تا رویداد داره یکی برا زمانی که روند اجرا تموم میشه Completedیکی برا گزارش حین کارشProgress_Changed و یکی هم هست که برا نوشتن دستوراتی که باید اجرا کنه DoWork
خب شما باید دستوراتتون رو توی رویداد doWork بنویسید و مقادیری که بدست میارید از اجرای دستورات رو توی همین نباید مستقیم به رویداد های تعریفی بفرستی ! اونارو باید پاس بدی به رویداد Progress_Changed خود بکگراند و از اونجا پاسش میدی به رویداد تعریفیی خودت

این ی نمونه از کار با Backgroundworker هست

M.KH-SH
جمعه 18 مرداد 1392, 03:10 صبح
ممنونم از نمونه کدی که دادین

دوست عزیز به شیوه شما در کلاس تغییراتی رو اعمال کردم خوب به ظاهر داره کار میکنه ولی به محض ورود موس به فرم exception میده و یا چند ثانیه بعد از اجرا خطا میده اینم بگم که چند بار نمایش رو دارم ولی خوب بازم جواب کامل نیست.

M.KH-SH
جمعه 18 مرداد 1392, 03:16 صبح
تا جایی که بشه نمی خوام از try به کاربر بگم استفاده کن و میخوام راحت از تابع استفاده کنه بدون خطا برای همین حساسیت دارم روش.

مهرداد صفا
جمعه 18 مرداد 1392, 03:39 صبح
در واقع نیاز دارم یک جواز بدم تا بشه از ترد جانبی در ترد اصلی استفاده کرد و به هم انتقال داده داشته باشن

با سلام.
چرا Control.CheckForIllegalCrossThreadCalls را برابر false نمی کنید:

public Component1()
{
Control.CheckForIllegalThreadCalls=false;
//...}

M.KH-SH
جمعه 18 مرداد 1392, 03:39 صبح
while (true)
{
Thread.Sleep(400);
bc.ReportProgress(DateTime.Now.Millisecond, DateTime.Now);
// Oneven("");
}

mousa1992
جمعه 18 مرداد 1392, 03:45 صبح
متن خطا رو قرار بده
و چک کن اطلاعاتی که فرستاده میشه ایا همیشه مقادیر صحیح میفرسته ینی ممکنه که null باشه و یا ی چیزی که باعث بشه روند برنامه متوقف بشه
متن خطاتو حتما بذار

M.KH-SH
جمعه 18 مرداد 1392, 03:58 صبح
با سلام.
چرا Control.CheckForIllegalCrossThreadCalls را برابر false نمی کنید:

خیلی ممنونم دقیقا مشکل من حل شد با تنظیم کردن این Property



متن خطا رو قرار بده
و چک کن اطلاعاتی که فرستاده میشه ایا همیشه مقادیر صحیح میفرسته ینی ممکنه که null باشه و یا ی چیزی که باعث بشه روند برنامه متوقف بشه
متن خطاتو حتما بذار
دوست خوبم از شما هم ممنونم خیلی محبت کردید و جواب سئوال های منو دادید.
مشکل با BackgroundWorker حل شد و مشکل با Thread هم حل شد.

خدا کنه که دیگه مشکل پیش نیاد :P

مهرداد صفا
جمعه 18 مرداد 1392, 04:21 صبح
خواهش می کنم.
به هر حال به عنوان یک option از کلاس System.ComponentModel.AsyncOperation (http://msdn.microsoft.com/en-us/library/system.componentmodel.asyncoperation%28v=vs.80%29. aspx) هم می توانید استفاده کنید.