为了账号安全,请及时绑定邮箱和手机立即绑定

C# 后台工作者追加文本框

C# 后台工作者追加文本框

C#
冉冉说 2021-11-21 11:06:50
首先,我想说我是 C# 的新手,所以我不太清楚后台工作人员应该如何实现。我有一个 GUI 程序,它基本上可以 ping 域并将响应返回到文本框。我能够让它正常工作,但是,它冻结了代码,因为它运行在同一个线程上,这就是我试图实现后台工作程序的原因。这是基本设置private void button1_Click(object sender, EventArgs e){    url = textBox1.Text;    button1.Enabled = false;    button2.Enabled = true;    bgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);    bgWorker.RunWorkerAsync();}private void bgWorker_DoWork(object sender, DoWorkEventArgs e){    do    {        if (bgWorker.CancellationPending)            break;        Invoke((MethodInvoker)delegate { monitor(); });    } while (true);}public void monitor(){    textBox2.AppendText("Status of: " + url + "\n");    Status(url);    System.Threading.Thread.Sleep(30000);}private void Status(string url){    // This method does all the ping work and also appends the status to the Text box as it goes through , as OK or down}我之前没有和 bgworkers 一起工作过,你可以想象这很令人困惑。我看过很多其他的文章,但似乎无法理解。对不起,如果代码看起来很疯狂,我正在努力学习。
查看完整描述

3 回答

?
鸿蒙传说

TA贡献1865条经验 获得超7个赞

使用微软的反应框架(NuGet“System.Reactive.Windows.Forms”并添加using System.Reactive.Linq;),然后你可以这样做:


private void button1_Click(object sender, EventArgs e)

{

    var url = textBox1.Text;

    Observable

        .Interval(TimeSpan.FromMinutes(0.5))

        .SelectMany(_ => Observable.Start(() => Status(url)))

        .ObserveOn(this)

        .Subscribe(status => textBox2.AppendText("Status of: " + status + "\n"));

}

然后,您只需要更改Status即可获得此签名:string Status(string url).


就是这样。没有后台工作人员。没有调用。并且Status很好地在后台线程上运行。


查看完整回答
反对 回复 2021-11-21
?
BIG阳

TA贡献1859条经验 获得超6个赞

你有几个错误。第一的,


Invoke((MethodInvoker)delegate

{

    monitor();

});

将调用monitor()您的 UI 线程。在几乎所有情况下,您都不应该在其他线程上调用方法。您尤其不应该调用在 UI 线程上阻塞或执行任何需要超过几毫秒的操作的方法,这就是这样做的:


System.Threading.Thread.Sleep(30000);

而不是在另一个线程上调用方法;向另一个线程提交不可变数据并让线程决定何时处理它。BackgroundWorker 中已经内置了一个事件来执行此操作。在您致电之前,请bgWorker.RunWorkerAsync()执行以下操作:


url = new Uri(something);

bgWorker.WorkerReportsProgress = true;

bgWorker.WorkerSupportsCancellation = true;

bgWorker.ProgressChanged += Bgw_ProgressChanged;



private void Bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)

{

    textBox2.AppendText("Status of: " + url + ": " + e.UserState.ToString()

        + Environment.NewLine);

}

你bgWorker_DoWork应该看起来更像这样:


void bgWorker_DoWork(object sender, DoWorkEventArgs e)

{

    while (!bgw.CancellationPending)

    {

        System.Threading.Thread.Sleep(new TimeSpan(0, 0, 30));

        var status = ResultOfPing(e.Argument as Uri);

        bgw.ReportProgress(0, status);

    }


    e.Cancel = true;

}

你应该这样称呼它:


bgWorker.RunWorkerAsync(url);

你还有第二个问题。BackgroundWorker 创建一个线程,并且您的线程将花费大部分时间在计时器上阻塞或等待网络响应。这是对线程的不良使用。您最好使用完成回调或async/await。


查看完整回答
反对 回复 2021-11-21
?
天涯尽头无女友

TA贡献1831条经验 获得超9个赞

试试这个代码:


public partial class Form1 : Form

{

    bool cancel;


    public Form1()

    {

        InitializeComponent();


    }


    public void StartPinging()

    {

        this.cancel = false;

        startButton.Enabled = false;

        stopButton.Enabled = true;

        responseBox.Clear();

        responseBox.AppendText("Starting to ping server.");

        responseBox.AppendText(Environment.NewLine);

        var bw = new BackgroundWorker

        {

            WorkerReportsProgress = false,

            WorkerSupportsCancellation = true

        };

        bw.DoWork += (obj, ev) =>

        {

            while (!cancel)

            {

                // Ping Server Here

                string response = Server.PingServer();


                this.Invoke(new UiMethod(() =>

                {

                    responseBox.AppendText(response);

                    responseBox.AppendText(Environment.NewLine);

                }));

            }

        };


        bw.RunWorkerCompleted += (obj, ev) =>

        {

            this.Invoke(new UiMethod(() =>

            {

                responseBox.AppendText("Stopped pinging the server.");

                responseBox.AppendText(Environment.NewLine);

                startButton.Enabled = true;

                stopButton.Enabled = false;

            }));

        };


        bw.RunWorkerAsync();

    }


    delegate void UiMethod();



    private void startButton_Click(object sender, EventArgs e)

    {

        StartPinging();

    }


    private void stopButton_Click(object sender, EventArgs e)

    {

        responseBox.AppendText("Cancelation Pressed.");

        responseBox.AppendText(Environment.NewLine);

        cancel = true;

    }

}


public class Server

{

    static Random rng = new Random();

    public static string PingServer()

    {

        int time = 1200 + rng.Next(2400);

        Thread.Sleep(time);

        return $"{time} ms";

    }

}

//img1.sycdn.imooc.com//6199b7f60001f6a108140487.jpg

查看完整回答
反对 回复 2021-11-21
  • 3 回答
  • 0 关注
  • 180 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信