উইনফোর্ডস প্রগতি বারটি কীভাবে ব্যবহার করবেন?


104

আমি গণনার অগ্রগতি প্রদর্শন করতে চাই, যা বাহ্যিক লাইব্রেরিতে সম্পাদন করে।

উদাহরণস্বরূপ, যদি আমার কিছু গণনা পদ্ধতি থাকে এবং আমি আমার ফর্ম শ্রেণিতে এটি 100000 মানের জন্য লিখতে পারি:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }            

    private void Caluculate(int i)
    {
        double pow = Math.Pow(i, i);
    }

    private void button1_Click(object sender, EventArgs e)
    {
        progressBar1.Maximum = 100000;
        progressBar1.Step = 1;

        for(int j = 0; j < 100000; j++)
        {
            Caluculate(j);
            progressBar1.PerformStep();
        }
    }
}

আমার প্রতিটি গণনার পরে পদক্ষেপ করা উচিত। তবে আমি যদি বাহ্যিক পদ্ধতিতে সমস্ত 100000 গণনা সম্পাদন করি। আমি যদি এই পদ্ধতিটিকে অগ্রগতির বারের উপর নির্ভরশীল করতে না চাই তবে আমার কখন "পদক্ষেপ" করা উচিত? আমি উদাহরণস্বরূপ লিখতে পারি

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void CaluculateAll(System.Windows.Forms.ProgressBar progressBar)
    {
        progressBar.Maximum = 100000;
        progressBar.Step = 1;

        for(int j = 0; j < 100000; j++)
        {
            double pow = Math.Pow(j, j); //Calculation
            progressBar.PerformStep();
        }
    }

    private void button1_Click(object sender, EventArgs e)
    {
        CaluculateAll(progressBar1);
    }
}

তবে আমি এর মতো করতে চাই না।


4
পদ্ধতিতে একটি প্রতিনিধি বস্তু পাস করুন।
হ্যানস প্যাস্যান্ট

উত্তর:


112

আমি আপনাকে ব্যাকগ্রাউন্ড ওয়ার্কারের দিকে নজর দিতে পরামর্শ দেব । আপনার উইনফোর্মে যদি এমন একটি লুপ থাকে তবে এটি আটকাবে এবং আপনার অ্যাপ্লিকেশনটি এটি ঝুলন্ত অবস্থায় দেখবে।

এ লুক BackgroundWorker.ReportProgress()UI 'তে থ্রেডে উন্নতি ফিরে রিপোর্ট করতে কিভাবে দেখতে।

উদাহরণ স্বরূপ:

private void Calculate(int i)
{
    double pow = Math.Pow(i, i);
}

private void button1_Click(object sender, EventArgs e)
{
    progressBar1.Maximum = 100;
    progressBar1.Step = 1;
    progressBar1.Value = 0;
    backgroundWorker.RunWorkerAsync();
}

private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
    var backgroundWorker = sender as BackgroundWorker;
    for (int j = 0; j < 100000; j++)
    {
        Calculate(j);
        backgroundWorker.ReportProgress((j * 100) / 100000);
    }
}

private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressBar1.Value = e.ProgressPercentage;
}

private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // TODO: do something with final calculation.
}

5
দুর্দান্ত উদাহরণ, তবে আপনার কোডটিতে একটি ছোট ত্রুটি রয়েছে। আপনাকে ব্যাকগ্রাউন্ড ওয়ার্কার.ওয়ার্কারের রিপোর্টসপ্রেস সেট করতে হবে to আমার সম্পাদনা পরীক্ষা করুন
মানা

4
@ মানা ধারণাটি হ'ল BackgroundWorkerডিজাইনারের মাধ্যমে যুক্ত করে সেখানে কনফিগার করা হয়েছে। তবে হ্যাঁ, WorkerReportsProgressসেট করার জন্য এটি কনফিগার করা দরকার true
পিটার রিচি

আহ, আমার খারাপ, আপনি এটি ডিজাইনারে সেট করতে পারেন তা জানতেন না
মানা

যদিও অন্য কিছু ভাবছেন, আপনার উদাহরণটি কেবল 99 ব্যাকগ্রাউন্ড ওয়ার্কার হিসাবে গণনা করে ep প্রতিবেদনপ্রগ্রো ((জে * 100) / 100000); 100% গণনা কীভাবে পাবেন
মানা

4
@ মানা আপনি যদি 100% অগ্রগতিতে দেখাতে চান তবে RunWorkerCompletedইভেন্ট হ্যান্ডলারে এটি করুন, যদি আপনার DoWorkহ্যান্ডলার এটি না করে থাকে ..
পিটার রিচি

78

নেট .৪.৪ থেকে আপনি অ্যাসিঙ্কের সংমিশ্রণটি ব্যবহার করতে পারেন এবং ইউআই থ্রেডে আপডেট প্রেরণের জন্য অগ্রগতির সাথে অপেক্ষা করতে পারেন :

private void Calculate(int i)
{
    double pow = Math.Pow(i, i);
}

public void DoWork(IProgress<int> progress)
{
    // This method is executed in the context of
    // another thread (different than the main UI thread),
    // so use only thread-safe code
    for (int j = 0; j < 100000; j++)
    {
        Calculate(j);

        // Use progress to notify UI thread that progress has
        // changed
        if (progress != null)
            progress.Report((j + 1) * 100 / 100000);
    }
}

private async void button1_Click(object sender, EventArgs e)
{
    progressBar1.Maximum = 100;
    progressBar1.Step = 1;

    var progress = new Progress<int>(v =>
    {
        // This lambda is executed in context of UI thread,
        // so it can safely update form controls
        progressBar1.Value = v;
    });

    // Run operation in another thread
    await Task.Run(() => DoWork(progress));

    // TODO: Do something after all calculations
}

কার্যগুলি বর্তমানে কার্যকর করার জন্য পছন্দসই উপায় BackgroundWorker

কাজগুলি এবং Progressআরও বিশদে এখানে ব্যাখ্যা করা হয়েছে:


4
এটি নির্বাচিত উত্তর, আইএমও হওয়া উচিত। দুর্দান্ত উত্তর!
জনঅপিনিকার

প্রায় সর্বাপেক্ষা উত্তম উত্তর, ব্যতীত এটি একটি সাধারণ
অ্যাসিঙ্ক

@ কানসাইরোবট আপনি কি বিরোধিতা করছেন await DoWorkAsync(progress);? এটি উদ্দেশ্য হিসাবে খুব বেশি কারণ এর ফলে অতিরিক্ত থ্রেড চলবে না running কেবলমাত্র DoWorkAsyncএটির awaitজন্য নিজেরাই যদি কল করেন যেমন I / O অপারেশনটির জন্য অপেক্ষা করছেন, তবে button1_Clickফাংশনটি চালু থাকবে । মূল ইউআই থ্রেড এই সময়ের জন্য অবরুদ্ধ। যদি DoWorkAsyncসত্যিই অ্যাসিঙ্ক না হয় তবে কেবলমাত্র অনেকগুলি সিনক্রোনাস স্টেটমেন্ট হয় তবে আপনি কিছু অর্জন করতে পারবেন না।
ওল্ফজুন 10

System.Windows.Controls.ProgressBar তে কোনও ক্ষেত্র "পদক্ষেপ" ধারণ করে না। এটি উদাহরণ থেকে অপসারণ করা উচিত; বিশেষত যেহেতু এটি কোনওভাবেই ব্যবহৃত হয় না।
রবার্ট তৌসিগ

4
@ রবার্টটৌসিগ এটি সত্য যে Stepকেবল উইনফর্মসের প্রগতি বারে উপলব্ধ এবং এখানে প্রয়োজনীয় নয়, তবে এটি প্রশ্নের উদাহরণের কোডটিতে উপস্থিত ছিল (ট্যাগযুক্ত উইনফর্মগুলি), তাই এটি থাকতে পারে।
Quasoft

4

আরে ডট নেট মুক্তো সম্পর্কে একটি দরকারী টিউটোরিয়াল রয়েছে: http://www.dotnetperls.com/progressbar

পিটারের সাথে চুক্তিতে আপনাকে কিছু পরিমাণ থ্রেডিং ব্যবহার করতে হবে বা প্রোগ্রামটি কেবল স্তব্ধ হয়ে যাবে, কিছুটা উদ্দেশ্যকে পরাস্ত করে।

প্রগতিবার এবং ব্যাকগ্রাউন্ড ওয়ার্কার ব্যবহার করে এমন উদাহরণ: সি #

using System.ComponentModel;
using System.Threading;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, System.EventArgs e)
        {
            // Start the BackgroundWorker.
            backgroundWorker1.RunWorkerAsync();
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            for (int i = 1; i <= 100; i++)
            {
                // Wait 100 milliseconds.
                Thread.Sleep(100);
                // Report progress.
                backgroundWorker1.ReportProgress(i);
            }
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            // Change the value of the ProgressBar to the BackgroundWorker progress.
            progressBar1.Value = e.ProgressPercentage;
            // Set the text.
            this.Text = e.ProgressPercentage.ToString();
        }
    }
} //closing here

1

এটি Taskবিদ্যমান, এটি ইউজনেসারী ব্যবহার করা সহজ BackgroundWorker, Taskআরও সহজ। উদাহরণ স্বরূপ:

অগ্রগতি ডায়ালগ.সি:

   public partial class ProgressDialog : Form
    {
        public System.Windows.Forms.ProgressBar Progressbar { get { return this.progressBar1; } }

        public ProgressDialog()
        {
            InitializeComponent();
        }

        public void RunAsync(Action action)
        {
            Task.Run(action);
        }
    }

সম্পন্ন! তারপরে আপনি যে কোনও জায়গায় অগ্রগতি ডায়ালগ পুনরায় ব্যবহার করতে পারেন:

var progressDialog = new ProgressDialog();
progressDialog.Progressbar.Value = 0;
progressDialog.Progressbar.Maximum = 100;

progressDialog.RunAsync(() =>
{
    for (int i = 0; i < 100; i++)
    {
        Thread.Sleep(1000)
        this.progressDialog.Progressbar.BeginInvoke((MethodInvoker)(() => {
            this.progressDialog.Progressbar.Value += 1;
        }));
    }
});

progressDialog.ShowDialog();

দয়া করে একাধিক প্রশ্নের একই উত্তর পোস্ট করবেন না । একটি ভাল উত্তর পোস্ট করুন, তারপরে অন্য প্রশ্নগুলিকে সদৃশ হিসাবে বন্ধ করতে ভোট / পতাকা দিন। যদি প্রশ্নটি সদৃশ না হয় তবে আপনার প্রশ্নের উত্তরগুলি শিখুন
মার্টিজন পিটারস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.