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 關注
- 207 瀏覽
添加回答
舉報