سؤال

أحاول فقط تشغيل سلسلة رسائل جديدة في كل مرة يحدث فيها زر النقر حتى ، والذي يجب أن ينشئ نموذجًا جديدًا. لقد جربت هذا في حدث Click Click in the Mainform:

private void button1_Click(object sender, EventArgs e)
{
    worker1 = new Thread(new ThreadStart(thread1));
    worker2 = new Thread(new ThreadStart(thread2));

    worker1.Start();
    worker2.Start();
}

private void thread1()
{
    SubForm s = new SubForm();
    s.Show();
}

private void thread2()
{
    SubForm s = new SubForm();
    s.Show();
}

الرمز في الحدث النقر فوق الزر الفرعي ينقر على هذا النحو:

private void button1_Click(object sender, EventArgs e)
{
    int max;
    try
    {
        max = Convert.ToInt32(textBox1.Text);
    }
    catch
    {
        MessageBox.Show("Enter numbers", "ERROR");
        return;
    }

    progressBar1.Maximum = max;

    for ( long i = 0; i < max; i++)
    {
        progressBar1.Value = Convert.ToInt32(i);
    }          
}

هل هذا هو الطريق الصحيح؟ لأنني أحاول فتح نموذجين مستقلين ، يجب ألا تؤثر العمليات في موضوع واحد على الخيط الآخر.

أم أن عمال الخلفية هو الحل لتنفيذ هذا؟ إذا كانت الإجابة بنعم ، هل يمكن لأي شخص مساعدتي في ذلك؟

هل كانت مفيدة؟

المحلول

على الرغم من أنني لست على دراية بنسبة 100 ٪ عن أي شيء يقول إن تشغيل النماذج المنفصلة تمامًا التي تقوم بعمليات معزولة تمامًا في خيوطها الخاصة أمر خطير بأي شكل من الأشكال ، فإن تشغيل جميع عمليات واجهة المستخدم على موضوع واحد يعتبر عمومًا ممارسة جيدة.

يمكنك دعم هذا ببساطة من خلال جعل الفئة الفرعية الخاصة بك استخدام خلفية. عندما يتم عرض النموذج ، قم بتشغيل عمال الخلفية بحيث يعالج كل ما تحتاج إليه.

ثم يمكنك ببساطة إنشاء مثيلات جديدة من الشكل الفرعي الخاص بك على موضوع واجهة المستخدم الرسومية وإظهارها. سيظهر النموذج ويبدأ تشغيله على موضوع آخر.

وبهذه الطريقة ، سيتم تشغيل واجهة المستخدم على مؤشر ترابط واجهة المستخدم الرسومية ، لكن العمليات التي يتم تشغيلها سيتم تشغيلها على مؤشرات ترابط ThreadPool.

تحديث

إليك مثال على ما قد يبدو عليه معالجات العمال في الخلفية - لاحظ أن هذا (كالمعتاد) هو خارج الجزء العلوي من رأسي ، لكنني أعتقد أنه يمكنك الحصول على رأسك حول المبادئ الأساسية.

أضف عامل خلفية إلى النموذج الخاص بك العامل المسمى. قم بربطه بمشغلات الأحداث التالية:

void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // Executed on GUI thread.
    if (e.Error != null)
    {
        // Background thread errored - report it in a messagebox.
        MessageBox.Show(e.Error.ToString());
        return;
    }

    // Worker succeeded.
}

void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    // Executed on GUI thread.
    progressBar1.Value = e.ProgressPercentage;
}

void worker_DoWork(object sender, DoWorkEventArgs e)
{
    // Executed on ThreadPool thread.
    int max = (int)e.Argument;

    for (long i = 0; i < max; i++)
    {
        worker.ReportProgress(Convert.ToInt32(i));
    }
}

سيبدو معالج النقرات الخاص بك مثل:

void button1_Click(object sender, EventArgs e)
{
    int max;

    try
    {
        // This is what you have in your click handler,
        // Int32.TryParse is a much better alternative.
        max = Convert.ToInt32(textBox1.Text);
    }
    catch
    {
        MessageBox.Show("Enter numbers", "ERROR");
        return;
    }

    progressBar1.Maximum = max;

    worker.RunWorkerAsync(max);
}

أتمنى أن يساعد ذلك.

نصائح أخرى

لا تحتاج إلى تشغيل النماذج في مؤشرات ترابط منفصلة. يمكنك الاتصال فقط s.Show() على أشكال متعددة بشكل طبيعي. لن يمنعوا بعضهم البعض.

بالطبع ، إذا كنت تفعل شيء آخر, ، مثل نوع من الحساب أو المهمة الأخرى التي تستغرق وقتًا طويلاً ، يجب عليك الركض الذي - التي في موضوع منفصل ، ولكن ليس النموذج.

فيما يلي القليل من التعليمات البرمجية التي تتيح لك إنشاء شريط تقدم يعرض التقدم لعملية طويلة. لاحظ أنه في كل مرة للوصول إلى النموذج من داخل الخيط ، عليك استخدامها .Invoke(), ، وهو في الواقع جدولة هذا الاحتجاج للتشغيل على موضوع واجهة المستخدم الرسومية عندما يكون جاهزًا.

public void StartLongProcess()
{
    // Create and show the form with the progress bar
    var progressForm = new Subform();
    progressForm.Show();
    bool interrupt = false;

    // Run the calculation in a separate thread
    var thread = new Thread(() =>
    {
        // Do some calculation, presumably in some sort of loop...
        while ( ... )
        {
            // Every time you want to update the progress bar:
            progressForm.Invoke(new Action(
                () => { progressForm.ProgressBar.Value = ...; }));

            // If you’re ready to cancel the calculation:
            if (interrupt)
                break;
        }

        // The calculation is finished — close the progress form
        progressForm.Invoke(new Action(() => { progressForm.Close(); }));
    });
    thread.Start();

    // Allow the user to cancel the calculation with a Cancel button
    progressForm.CancelButton.Click += (s, e) => { interrupt = true; };
}

جرب هذا. يدير النموذج الجديد على موضوعه الخاص مع قوائم قوائم رسائله الخاصة وما لا. قم بتشغيل هذا الرمز:

new Thread(new ThreadStart(delegate
{
   Application.Run(new Form());
})).Start();

يستخدم Thread.CurrentThread.GetHashCode() لاختبار ذلك يتم تشغيله على موضوع مختلف.

من الممكن تشغيل أشكال مختلفة على خيوط مختلفة. هناك نوعان من التحذيرات التي أدركها:

  1. قد لا يكون أي من العميل MDI من الآخر. محاولة جعل نموذج عميل MDI من آخر عندما تفشل النماذج مؤشرات ترابط مختلفة.
  2. إذا كان الكائن هو إرسال الأحداث إلى نماذج متعددة وتستخدم جميع النماذج نفس الخيط ، فمن الممكن مزامنة الأحداث مع الخيط الرئيسي قبل رفعه. خلاف ذلك ، يجب رفع الحدث بشكل غير متزامن ويجب أن يؤدي كل نموذج آلية التزامن الخاصة به للأحداث الواردة.

من الواضح أنه من المستحسن عدم حظر خيط واجهة المستخدم في أي نافذة ، ولكن قد يكون استخدام مؤشرات ترابط منفصلة لنوافذ منفصلة بديلاً لطيفًا.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top