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很好地在后台线程上运行。
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。
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";
}
}
- 3 回答
- 0 关注
- 180 浏览
添加回答
举报