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

نام تاپیک: عدم مقدار دهی متغییر از نوع رشته ای در backgroundWorker1_DoWork_1

  1. #1

    عدم مقدار دهی متغییر از نوع رشته ای در backgroundWorker1_DoWork_1

    سلام دوستان چرا در این قسمت نمی توان به متغییر هایی که رشته ای هستن مقدار داد اگه ترفندی هست لطفا راهنمایی کنید با تشکر

    private void backgroundWorker1_DoWork_1(object sender, DoWorkEventArgs e)
    {
    progressBar1.Maximum = 100;

    for (int i = 0; i <= 100; i++)
    {
    label2.Text = i.ToString();
    System.Threading.Thread.Sleep(1);
    backgroundWorker1.ReportProgress(i);
    }
    }

  2. #2

    نقل قول: عدم مقدار دهی متغییر از نوع رشته ای در backgroundWorker1_DoWork_1

    کسی از دوستان با این خطا برخورد نکرد
    عکس های ضمیمه عکس های ضمیمه

  3. #3

    نقل قول: عدم مقدار دهی متغییر از نوع رشته ای در backgroundWorker1_DoWork_1

    نقل قول نوشته شده توسط mustafa13 مشاهده تاپیک
    کسی از دوستان با این خطا برخورد نکرد
    سلام.
    پست شماره 9 از این تاپیک رو مطالعه کنید.

    موفق باشید.

  4. #4

    نقل قول: عدم مقدار دهی متغییر از نوع رشته ای در backgroundWorker1_DoWork_1

    نقل قول نوشته شده توسط mehdi.mousavi مشاهده تاپیک
    ضمن تشکر از تون
    اگه قبل از حلقه باشه و یا در حلقه هم اگه شرطی که برقرار شد چی باز هم نیم توان برای متغییری که رشته ای هست مقدار دهی کرد

  5. #5

    نقل قول: عدم مقدار دهی متغییر از نوع رشته ای در backgroundWorker1_DoWork_1

    نقل قول نوشته شده توسط mustafa13 مشاهده تاپیک
    ضمن تشکر از تون اگه قبل از حلقه باشه و یا در حلقه هم اگه شرطی که برقرار شد چی باز هم نیم توان برای متغییری که رشته ای هست مقدار دهی کرد
    سلام.
    متوجه سوالتون نمیشم. شما توی Worker Thread خودتون، اجازه دسترسی به UI Control ها رو ندارید... به روشی که در پست شماره 9 اون تاپیک توضیح دادم، عمل کنید. اگر مشکلی پیش اومد، اونوقت مطرح کنید تا بهش پاسخ بدم.

    موفق باشید.

  6. #6

    نقل قول: عدم مقدار دهی متغییر از نوع رشته ای در backgroundWorker1_DoWork_1

    اصولا چیزی که میگید هیچ ربطی به قبل از حلقه یا بعد از حلقه بودن و متغیر رشته ای بودن نداره.
    شما میتونید هرجائی که خواستید و هر نوع داده ای رو که خواستید برگردونید به UI Thread
    اینجا توضیح داده که چطور این کار رو انجام بدید.
    How to: Make Thread-Safe Calls to Windows Forms Controls

    در واقع کلمه کلید و مهم در اینجا استفاده از this.Invoke هست(البته اگه از Windowm Form ) استفاده میکنید.

  7. #7

    نقل قول: عدم مقدار دهی متغییر از نوع رشته ای در backgroundWorker1_DoWork_1

    سلام
    ضمن تشکر از استاتید محترم
    ممکن که از ویندوز من باشد چون ویندوز من ویندوز 7
    حال من کل سورس را می گذارم لطفا تست کنید ببینید رو دستگاه من همون خطایی که گفتم را می هد از راهنمایی هاتون متشکرم
    فایل های ضمیمه فایل های ضمیمه

  8. #8

    نقل قول: عدم مقدار دهی متغییر از نوع رشته ای در backgroundWorker1_DoWork_1

    شما لینکی که دادم رو خوندید؟

    مثال از همون لینک:

    // Check if this method is running on a different thread
    // than the thread that created the control.
    if (this.textBox1.InvokeRequired)
    {
    // It's on a different thread, so use Invoke.
    SetTextCallback d = new SetTextCallback(SetText);
    this.Invoke
    (d, new object[] { text + " (Invoke)" });
    }
    else
    {
    // It's on the same thread, no need for Invoke
    this.textBox1.Text = text + " (No Invoke)";
    }

  9. #9

    نقل قول: عدم مقدار دهی متغییر از نوع رشته ای در backgroundWorker1_DoWork_1

    سلام
    سال نو را به همه دوستان تبریک عرض می کنم انشاالله سالی خوبی باشه براتون در کنار خانواده محترم تان
    کسی به این مثال من نگاه نکرده

  10. #10

    نقل قول: عدم مقدار دهی متغییر از نوع رشته ای در backgroundWorker1_DoWork_1

    نقل قول نوشته شده توسط mehdi.mousavi مشاهده تاپیک
    سلام.
    متوجه سوالتون نمیشم. شما توی Worker Thread خودتون، اجازه دسترسی به UI Control ها رو ندارید... به روشی که در پست شماره 9 اون تاپیک توضیح دادم، عمل کنید. اگر مشکلی پیش اومد، اونوقت مطرح کنید تا بهش پاسخ بدم.

    موفق باشید.
    سلام
    ممکن مثالی را که ضمیمه کرده ام را تست کنی متشکرم

  11. #11

    نقل قول: عدم مقدار دهی متغییر از نوع رشته ای در backgroundWorker1_DoWork_1

    نقل قول نوشته شده توسط mustafa13 مشاهده تاپیک
    سلام ممکن مثالی را که ضمیمه کرده ام را تست کنی متشکرم
    سلام.
    من توابعی که نوشتید رو اینجا میارم تا دیگه نیازی به Download کردن و دیدن کد توسط دیگران نباشه:


    private void button1_Click(object sender, EventArgs e)
    {

    backgroundWorker1.WorkerReportsProgress = true;
    progressBar1.Maximum = 1000;
    backgroundWorker1.RunWorkerAsync();

    }

    private void backgroundWorker1_DoWork_1(object sender, DoWorkEventArgs e)
    {
    textBox1.Text = "";
    for (int i = 0; i <= 1000; i++)
    {
    System.Threading.Thread.Sleep(5);
    backgroundWorker1.ReportProgress(i);
    if ((i / 2) > 1)
    textBox1.Text = textBox1.Text + textBox1.Text;
    }
    }

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
    progressBar1.Value = e.ProgressPercentage;
    label1.Text = e.ProgressPercentage.ToString();
    }


    من برنامه شما رو اجرا نکردم چون وقتی کد DoWork رو دیدم، نا امید شدم. من بهتون گفتم، که شما نباید توی backgroundWorker1_DoWork_1 به UI Element ها کاری داشته باشید اما بازهم شما دارید textBox1.Text رو Set می کنید! اینکار اشتباهه! هر کاری که مایلید روی UI انجام بدید، باید توی متود backgroundWorker1_ProgressChanged انجام بدید.

    @همه: به خاطر خدا پاسخهایی رو که میدم درست و دقیق بخونید.

  12. #12

    نقل قول: عدم مقدار دهی متغییر از نوع رشته ای در backgroundWorker1_DoWork_1

    سلام.
    پیرو صحبتهایی که داشتیم (در پیامهای خصوصی)، من کد شما رو بدین شکل تغییر دادم: (البته اینجا میذارم تا اگر افراد دیگری هم همین سوال رو داشتن، پاسخشون رو بگیرن).


    private void button1_Click(object sender, EventArgs e)
    {
    textBox1.Text = "";
    backgroundWorker1.WorkerReportsProgress = true;
    backgroundWorker1.RunWorkerAsync();
    }

    private void backgroundWorker1_DoWork_1(object sender, DoWorkEventArgs e)
    {
    for (int i = 0; i <= 1000; i++)
    {
    System.Threading.Thread.Sleep(5);
    backgroundWorker1.ReportProgress(i * 100 / 1000, "Obj#" + i);
    }
    }

    private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
    string result = e.UserState as string;
    textBox1.Text += result;

    progressBar1.Value = e.ProgressPercentage;
    label1.Text = e.ProgressPercentage.ToString();
    label1.Refresh();
    }


    خوب. تغییرات چی بود؟

    • Range ای که شما برای ProgressBar تعیین کرده بودید رو من حذف کردم، تا همون 0 تا 100 خودش باقی بمونه. چرا اینکارو کردم؟ چون ReportProgress یک عدد بین 0 تا 100 انتظار بهش بدیم، در صورتیکه کد شما ممکن بود تا عدد 1000 رو هم به این تابع بده!
    • تغییر بعدی، حذف کلیه عملیاتی بود که شما روی TextBox و توی تابع DoWork انجام می دادید. شما اجازه ندارید به UI Element ها از درون این تابع دسترسی پیدا کنید. چرا؟ چون DoWork داره تو Context یک Thread دیگه اجرا میشه و به UI Element ها باید حتما از Thread ای که UI رو ایجاد کرده دسترسی پیدا کرد. این مساله در C++‎ و بقیه زبانها نیز صادقه و ربطی به C#‎ نداره.
    • به ReportProgress یک پارامتر دوم اضافه کردم، پارامتری که نیاز دارم توی ProgressChanged بهش دسترسی پیدا کنم. دقت کنید. اینجا تمام اون چیزی هستش که شما برای Marshaling داده ها بین این دو Thread نیاز دارید. من، string ای ساختم که i رو هر سری بهش اضافه میکنم و بعد پیشرفت رو با ReportProgress گزارش میدم. بدین ترتیب، توی متود backgroundWorker1_ProgressChanged، از روی پارامتر دوم، میتونم به این string (یا هر object ای که مایل بودید) دسترسی داشته باشم. چون string تعریف کرده بودم، با کد زیر هم اونو گرفتم:

    string result = e.UserState as string;


    و توی همین تابع، با خیالی راحت، textBox1.Text رو تغییر میدم. فقط اینجا یک نکته دیگه میمونه! اونم اینکه وقتی با این تغییراتی که گفتم برنامه رو اجرا کنید، متوجه میشید که Label تغییری نکرده و فقط تا شماره خاصی Refresh میشه و بعد روی عدد 100 (یعنی 100%) دوباره Refresh میشه و نمایش داده میشه. این ایراد چی هستش و چطور باید رفعش کرد؟

    وقتی شما توی ProgressChanged دارید Label رو تغییر میدید، منظورم با این خط از کد هستش:

    label1.Text = e.ProgressPercentage.ToString();


    در واقع برنامه داره دستور مزبور رو توی صف پیامهای ویندوز میذاره. تا وقتی این پیامها پردازش نشن، label جدید مشاهده نمیشه... Sleep ای که شما گذاشته اید، Thread رو برای 5 میلی ثانیه متوقف میکنه، حالا 5 میلی ثانیه فرصت داره ویندوز تا توی یک Context Swithing، بره و Label شما رو Refresh کنه. اما قبل از اینکه اینکارو انجام بده، 5 میلی ثانیه طی شده و Context Switching به Worker Thread دوباره باعث میشه تا Main Thread نرسه که کارش رو انجام بده. اگر 5 میلی ثانیه رو بیشتر کنید، مشکل حل میشه، اما اگر همون 5 میلی ثانیه بخواهید نگهدارید، باید بعد تغییر Label اونو به زور Refresh کنید. به بیان دیگه، به Windows بفهمونید که الان باید Label شما رو Invalidate کنه و ...

    اون خط از کد که من نوشتم برای Refresh بخاطر این بوده. البته، توصیه میکنم اون 5 میلی ثانیه رو افزایش بدید. قاعدتا با 20 میلی ثانیه، مشکلی مزبور پیش نمیاد و نیازی به Refresh کردن Label بصورت Explicit ندارید.

    موفق باشید.

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

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