نمایش نتایج 1 تا 14 از 14

نام تاپیک: مشکل در ارتباط بین دو Thread

  1. #1

    مشکل در ارتباط بین دو Thread

    سلام
    قبل از هر چیزی بخاطر عنوان نه چندان جالب ببخشید هر چی فکر کردم واسه مشکلم چه عنوانی بذارم ...!!
    توی برنامه ام قراره یک سری کارهای وقت گیر انجام بشه (زمان اجرای کل تقریبا 4 دقیقه میشه) . برای جلوگیری از به حالت هنگ رفتن برنامه همه کارها رو توی یه نخ دیگه انجام میدم. زمانی هم که اون نخ رو استارت میزنم یه فرم لودینگ ظاهر میشه. تا اینجای کار هیچ مشکلی نیست ، مشکل من اینه که میخوام وقتی کار این نخ تموم شد صفحه لودینگ هم بسته بشه. برای این کار بصورت زیر عمل کردم:
    اول یه نخ درست کردم و اونو استارت زدم در همون حین فرم لودینگ رو هم نمایش میدم

    private void btnStart_Click(object sender, EventArgs e)
    {
    ManagerThread = new Thread(new ThreadStart(CreatePrimalPopulation));
    LoadingForm.Show();
    ManagerThread.Start();
    }

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

    void CreatePrimalPopulation()
    {
    ...
    ...
    ...
    LoadingForm.Close();
    }


    ولی نمیدونم چرا زمانی که به خط بسته شدن فرم لودینگ میرسه خطا میگیره(Exception) متن این خطا هم اینه
    Cross-thread operation not valid: Control 'Loading' accessed from a thread other than the thread it was created on.

    حالا به نظر شما چطور باید این مشکل رو برطرف کرد؟

  2. #2
    کاربر دائمی
    تاریخ عضویت
    فروردین 1386
    محل زندگی
    آستارا-تهران
    پست
    357

    نقل قول: مشکل در ارتباط بین دو Thread

    قبلش این کد رو بنویس ببین درست میشه؟
    Control.CheckForIllegalCrossThreadCalls = false;

  3. #3
    کاربر دائمی آواتار Saeed_m_Farid
    تاریخ عضویت
    تیر 1386
    محل زندگی
    فضای تهی میان دیوارها
    سن
    44
    پست
    1,046

    نقل قول: مشکل در ارتباط بین دو Thread

    نقل قول نوشته شده توسط mohsen_csharp مشاهده تاپیک
    قبلش این کد رو بنویس ببین درست میشه؟
    Control.CheckForIllegalCrossThreadCalls = false;
    شما داری روی صورت مساله رو پاک می کنی.
    دلیل این که شما این خطا رو دریافت می کنید، اینه که شما از Thread فرزند دارین به ایجاد کننده اون access می کنید و می بندینش.
    به نظر من بهتره اینکار از طریق ارسال پیام به LoadingForm تون انجام بشه، برای اینکار باید بعد اتمام کارتون تو Thread موردنظر Stop اش کنید و یه پیغام برای LoadingForm بفرستین که خودش رو ببنده، برای قسمت دوم هم (یعنی دریافت پیام توسط LoadingForm) باید Windows procedure رو override کنید، مثلاً اینطوری :
    protected override void WndProc(ref Message mess ){
    // Listen for operating system messages.
    switch( mess.Msg ) {
    case WM_CLOSE_LOADINGFORM: {
    // کارهایی که میخواهید انجام بدین
    LoadingForm.Close(); // or this.Close();
    break;
    }

    base.WndProc(ref mess);
    }
    }
    البته این ثابت WM_CLOSE_LOADINGFORM رو هم باید تعریف کنید و از طریق همون پیام به فرمتون دستور بسته شدن بدید :
    // اول برنامه
    private const int WM_CLOSE_LOADINGFORM = 0x4FF0;

    // برای ارسال پیام
    [DllImport("user32.dll", CharSet=CharSet.Auto)]
    public static extern int PostMessage(HandleRef hwnd, int msg, IntPtr wparam, IntPtr lparam);

  4. #4
    کاربر دائمی آواتار pesar irooni
    تاریخ عضویت
    بهمن 1386
    محل زندگی
    تهران
    سن
    40
    پست
    495

    نقل قول: مشکل در ارتباط بین دو Thread

    چون اون فرم که لودکردی خودش تو یه نخ دیگه داره اجرا میشه و شما میخوای از یه نخ که داره همزمان با اون اجرا میشه محتویات نخ دیگه رو دستکاری کنی و این اجازه در حالت پیش فرض به شما داده نمیشه.
    میتونی به جز کاری که دوستمون گفت دو کار انجام بدی. یکی اینکه تو یه حلقه با بازه زمانی مثلا 1 ثانیه چک کنی ببینی نخ هنوز داره کار میکنه (با متد IsAlive یا همین چیزی از خود نخ) و یا یه چیزی شبیه InvokeRequired برای فرم پیدا کنی. مثلا من میخواستم داخل یه نخ یکی از کنرلهای فرمم رو تغییر بدم همون خطای شما رو میداد و من مثل این کد رو نوشتم :
    public void SetStatus( string text )
    {
    if (LoadingForm.InvokeRequired)
    {
    this.Label_Status.BeginInvoke(
    new MethodInvoker(
    delegate() { SetStatus( text ); } ) );
    }
    else
    {
    this.Label_Status.Text = text;
    }
    }

  5. #5
    کاربر دائمی
    تاریخ عضویت
    فروردین 1388
    محل زندگی
    تهران
    پست
    123

    نقل قول: مشکل در ارتباط بین دو Thread

    ساده ترین راه در کار بر روی کنترل های windows در Thread های جداگانه این است که اجرای دستورات را به thread ی که کنترل را ایجاد کرده است برگردانید
    در مثال شما:

    this.Invoke(new MethodInvoker(delegate()
    {
    LoadingForm.Close();
    }));


    اگر خواستید بگویید توضیح می دهم

  6. #6
    کاربر دائمی آواتار hamid67fathi
    تاریخ عضویت
    بهمن 1386
    محل زندگی
    WwW
    پست
    435

    نقل قول: مشکل در ارتباط بین دو Thread

    ممنون ميشم اگه بيشتر توضيح بديد !!
    من همين مشکل رو با BackGroundWorker دارم !

  7. #7

    Question نقل قول: مشکل در ارتباط بین دو Thread

    من یک فرم لودینگ دارم که تووش پروگرس بار است.
    یک فرم هم دارم که تووش درخت است و با تابعی پر از دیتا میشود.
    اینگونه عمل کرده ام:
    این رو نوشتم توو فرم که درخت تووشه که بتونم فرم لودینگ رو شو کنم:
    LoadingForm frmp;


    اینم توو لود فرمه که تووش درخته:
    frmp = new LoadingForm();
    frmp.Show();
    this.Cursor = Cursors.WaitCursor;
    backgroundWorker1.RunWorkerAsync();


    اینم توو دوو ورک بکگرادنورکر:
    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
    int returnedRecordCount = 100;
    for (int i = 1; i <= returnedRecordCount; i++)
    {
    if (this.backgroundWorker1.CancellationPending)
    {
    e.Cancel = true;
    return;
    }
    this.backgroundWorker1.ReportProgress(i);

    System.Threading.Thread.Sleep(20);
    }
    if (TrvCoding.InvokeRequired)
    {

    TrvCoding.Invoke(new MethodInvoker(delegate { TvfCoding.LoadTreeFullDate(); }));

    //TvfCoding.LoadTreeFullDate();
    }
    }


    اینم توو کامپلیت:
    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
    this.Cursor = Cursors.Default;
    frmp.Close();
    //frmp.Hide();
    }


    اینم وقتی که فرمه که تووش درخته،دارخ بسته میشه:
    private void HesabStateWorkForm_FormClosed(object sender, FormClosedEventArgs e)
    {
    if (this.backgroundWorker1.IsBusy) this.backgroundWorker1.CancelAsync();
    }

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
    if (e.ProgressPercentage <= this.frmp.progressBar1.Maximum)
    {
    this.frmp.progressBar1.Value = e.ProgressPercentage;
    }
    }


    اینم توو لود فرم لودینگ:
    progressBar1.Value = 0;
    for (int x = 0; x < 100; x++)
    {
    if (progressBar1.Value < progressBar1.Maximum)
    {
    //System.Threading.Thread.Sleep(10);
    progressBar1.Value++;
    }
    }


    اینا هم نکته ها:
    دو تا پروپرتی توانایی کنسل کردن و گزارش دادن true است.
    و
    فرم لودینگ هم TopMost = true

    سوالات:
    الآن همه چی میاد،عالی...
    ولی
    اول لودینگ میاد،بعد پر شدن درخت شروع میشه!

    من میخوام هم زمان باشن!


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

    اگر مورد بالا نشد،میخوام که پروگرس بار بلوکی نباشد،marquee باشد.(style)

  8. #8

    نقل قول: مشکل در ارتباط بین دو Thread


  9. #9

    Thumbs down نقل قول: مشکل در ارتباط بین دو Thread

    نقل قول نوشته شده توسط tooraj_azizi_1035 مشاهده تاپیک
    مرسی ولی چیز خاصی واسه حل شدن مشکل من نداش!

  10. #10
    کاربر دائمی آواتار mahdi87_gh
    تاریخ عضویت
    فروردین 1388
    محل زندگی
    قزوین
    پست
    448

    نقل قول: مشکل در ارتباط بین دو Thread

    دوست عزیز در فرم لودینگ بجای قرار دادن یه حلقه for الکی، از یه عکس gif استفاده کنید.
    دز موقع شروع بکار backgroundWorker فرم لودینگ رو نمایش داده و در موقع پایان کار backgroundWorker فرم لودینگ رو ببندید. اگر مشکل برخوردید، اطلاع بدین تا یه نمونه قرار بدم

  11. #11

    Unhappy نقل قول: مشکل در ارتباط بین دو Thread

    نقل قول نوشته شده توسط mahdi87_gh مشاهده تاپیک
    دوست عزیز در فرم لودینگ بجای قرار دادن یه حلقه for الکی، از یه عکس gif استفاده کنید.
    دز موقع شروع بکار backgroundWorker فرم لودینگ رو نمایش داده و در موقع پایان کار backgroundWorker فرم لودینگ رو ببندید. اگر مشکل برخوردید، اطلاع بدین تا یه نمونه قرار بدم
    اگه این تغییری که شما گفتینو بکنم...1 ثانیه لوینگ میاد،میره،فرمی که درخت تووشه،رو میشه تکوون داد.

    اگه لطف کنید یک نمونه بزارین ممنون میشم.

    البته مثالی که میزنید لطفا طوری باشه که 100% تابع پر کردن درختم توو این تیکه باشه:
    if (TrvCoding.InvokeRequired)
    {

    TrvCoding.Invoke(new MethodInvoker(delegate { TvfCoding.LoadTreeFullDate(); }));

    //TvfCoding.LoadTreeFullDate();
    }

  12. #12
    کاربر دائمی آواتار mahdi87_gh
    تاریخ عضویت
    فروردین 1388
    محل زندگی
    قزوین
    پست
    448

    نقل قول: مشکل در ارتباط بین دو Thread

    دوست عزیز من با backgroundWorker انجام دادم اما یه اروری داشت که دیگه حال نداشتم بگردم درستش کنم. از یه روش دیگه که قبلا اسنفاده کرده بودم یه مثال میزارم نگاه کن
    فایل های ضمیمه فایل های ضمیمه

  13. #13

    نقل قول: مشکل در ارتباط بین دو Thread

    نقل قول نوشته شده توسط mahdi87_gh مشاهده تاپیک
    دوست عزیز من با backgroundWorker انجام دادم اما یه اروری داشت که دیگه حال نداشتم بگردم درستش کنم. از یه روش دیگه که قبلا اسنفاده کرده بودم یه مثال میزارم نگاه کن

    ممنون ولی این مشکل من نیس!!!!!!

    اصلا شما از backgroundworker استفاده نکردین!!!!!

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

    اصلا این روش ترد دستی رو نمیخوام
    Just backGroundWorker
    آخرین ویرایش به وسیله dr_jacky_2005 : یک شنبه 02 آبان 1389 در 15:43 عصر

  14. #14

    Angry نقل قول: مشکل در ارتباط بین دو Thread

    نقل قول نوشته شده توسط dr_jacky_2005 مشاهده تاپیک
    من یک فرم لودینگ دارم که تووش پروگرس بار است.
    یک فرم هم دارم که تووش درخت است و با تابعی پر از دیتا میشود.
    اینگونه عمل کرده ام:
    این رو نوشتم توو فرم که درخت تووشه که بتونم فرم لودینگ رو شو کنم:
    LoadingForm frmp;
    اینم توو لود فرمه که تووش درخته:
    frmp = new LoadingForm();
    frmp.Show();
    this.Cursor = Cursors.WaitCursor;
    backgroundWorker1.RunWorkerAsync();
    اینم توو دوو ورک بکگرادنورکر:
    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
    int returnedRecordCount = 100;
    for (int i = 1; i <= returnedRecordCount; i++)
    {
    if (this.backgroundWorker1.CancellationPending)
    {
    e.Cancel = true;
    return;
    }
    this.backgroundWorker1.ReportProgress(i);

    System.Threading.Thread.Sleep(20);
    }
    if (TrvCoding.InvokeRequired)
    {

    TrvCoding.Invoke(new MethodInvoker(delegate { TvfCoding.LoadTreeFullDate(); }));

    //TvfCoding.LoadTreeFullDate();
    }
    }
    اینم توو کامپلیت:
    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
    this.Cursor = Cursors.Default;
    frmp.Close();
    //frmp.Hide();
    }
    اینم وقتی که فرمه که تووش درخته،دارخ بسته میشه:
    private void HesabStateWorkForm_FormClosed(object sender, FormClosedEventArgs e)
    {
    if (this.backgroundWorker1.IsBusy) this.backgroundWorker1.CancelAsync();
    }

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
    if (e.ProgressPercentage <= this.frmp.progressBar1.Maximum)
    {
    this.frmp.progressBar1.Value = e.ProgressPercentage;
    }
    }
    اینم توو لود فرم لودینگ:
    progressBar1.Value = 0;
    for (int x = 0; x < 100; x++)
    {
    if (progressBar1.Value < progressBar1.Maximum)
    {
    //System.Threading.Thread.Sleep(10);
    progressBar1.Value++;
    }
    }
    اینا هم نکته ها:
    دو تا پروپرتی توانایی کنسل کردن و گزارش دادن true است.
    و
    فرم لودینگ هم TopMost = true

    سوالات:
    الآن همه چی میاد،عالی...
    ولی
    اول لودینگ میاد،بعد پر شدن درخت شروع میشه!

    من میخوام هم زمان باشن!


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

    اگر مورد بالا نشد،میخوام که پروگرس بار بلوکی نباشد،marquee باشد.(style)
    کسی نیست کمک کنه؟

قوانین ایجاد تاپیک در تالار

  • شما نمی توانید تاپیک جدید ایجاد کنید
  • شما نمی توانید به تاپیک ها پاسخ دهید
  • شما نمی توانید ضمیمه ارسال کنید
  • شما نمی توانید پاسخ هایتان را ویرایش کنید
  •