我逐行处理文件,读取具有时间戳和相关数据的各种事件。我想要能够显示一个表单,同时进行处理,我需要与之交互和截取一些事件,有一个按钮说中断EventX,如果它被按下,它将显示一个丰富的文本框字段中的事件数据,当这个事件在未来的某个时候到达。然后,我可以更改一些事件数据(假设我模拟了一些条件),当我按下" resume“时,它应该通过向目标订阅者引发一个事件以进行进一步处理来恢复处理。
因此,我需要一个拦截器,当某个表单元素被按下并将数据传递给目标订阅者时,它将通过传递机制。我可以同步等待修改数据并按"Resume“
谢谢
发布于 2018-02-14 08:30:40
如果您希望在执行长时间运行的操作时具有响应式GUI,则需要某种形式的多任务处理。这意味着异步/等待或许多多线程(主要是线程和BackgroundWorker )方法中的任何一种
虽然可以添加暂停和恢复,但这样做通常比值得做的工作更多。至少,你会遇到一些问题,比如仍然保留的文件句柄或竞争条件。通常,“取消”操作比完全停止/继续操作要好得多。
作为一个初学者,我建议你使用BackgroundWorker。这几乎是通过多线程进入多任务处理的最简单方法。几年前,我甚至为它写了一个例子:
#region Primenumbers
private void btnPrimStart_Click(object sender, EventArgs e)
{
if (!bgwPrim.IsBusy)
{
//Prepare ProgressBar and Textbox
int temp = (int)nudPrim.Value;
pgbPrim.Maximum = temp;
tbPrim.Text = "";
//Start processing
bgwPrim.RunWorkerAsync(temp);
}
}
private void btnPrimCancel_Click(object sender, EventArgs e)
{
if (bgwPrim.IsBusy)
{
bgwPrim.CancelAsync();
}
}
private void bgwPrim_DoWork(object sender, DoWorkEventArgs e)
{
int highestToCheck = (int)e.Argument;
//Get a reference to the BackgroundWorker running this code
//for Progress Updates and Cancelation checking
BackgroundWorker thisWorker = (BackgroundWorker)sender;
//Create the list that stores the results and is returned by DoWork
List<int> Primes = new List<int>();
//Check all uneven numbers between 1 and whatever the user choose as upper limit
for(int PrimeCandidate=1; PrimeCandidate < highestToCheck; PrimeCandidate+=2)
{
//Report progress
thisWorker.ReportProgress(PrimeCandidate);
bool isNoPrime = false;
//Check if the Cancelation was requested during the last loop
if (thisWorker.CancellationPending)
{
//Tell the Backgroundworker you are canceling and exit the for-loop
e.Cancel = true;
break;
}
//Determin if this is a Prime Number
for (int j = 3; j < PrimeCandidate && !isNoPrime; j += 2)
{
if (PrimeCandidate % j == 0)
isNoPrime = true;
}
if (!isNoPrime)
Primes.Add(PrimeCandidate);
}
//Tell the progress bar you are finished
thisWorker.ReportProgress(highestToCheck);
//Save Return Value
e.Result = Primes.ToArray();
}
private void bgwPrim_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
pgbPrim.Value = e.ProgressPercentage;
}
private void bgwPrim_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
pgbPrim.Value = pgbPrim.Maximum;
this.Refresh();
if (!e.Cancelled && e.Error == null)
{
//Show the Result
int[] Primes = (int[])e.Result;
StringBuilder sbOutput = new StringBuilder();
foreach (int Prim in Primes)
{
sbOutput.Append(Prim.ToString() + Environment.NewLine);
}
tbPrim.Text = sbOutput.ToString();
}
else
{
tbPrim.Text = "Operation canceled by user or Exception";
}
}
#endregion发布于 2018-02-18 08:18:08
谢谢你,克里斯托弗
我接受了你的回答,因为你给了我一些如何解决我的问题的建议。你可以看到下面我是如何解决这个问题的。
Rad
//class variable
private SimulatorRunner simulatorRunner;
//Code behind DevicesSimulatorForm form
private void RunSimulator()
{
btnRerun.BackColor = Color.BurlyWood;
ParameterizedThreadStart start = new ParameterizedThreadStart(RunSimulator);
Thread simulatorProcessingThread = new Thread(start);
simulatorProcessingThread.Start(this);
}
//This will run in a separate thread so when accessing controls Invoke is being used.
public void RunSimulator(object form)
{
DevicesSimulatorForm devicesSimulatorForm = (DevicesSimulatorForm) form;
simulatorRunner.Run(devicesSimulatorForm);
devicesSimulatorForm.InvokeEx(formInner =>
{
formInner.btnRerun.BackColor = Color.LightGray;
InitializeFields();
InitializeTextBackBorder();
InitializeButtonControls();
running = false;
});
}
public class SimulatorRunner
{
public void Run(DevicesSimulator form)
{
string buffer = "Some content read from file in a loop that needs to be passed
to a rich text box when a boolean Intercept check box is true
and FormStatusIntercept will return true and with Thread.Sleep(1)
we will have a chance to update the buffer to the new value and by
unchecking Intercept check box we will exit while loop and continue
processing"
while (true)
{
if (FormStatusIntercept(form, ref buffer))
{
Thread.Sleep(1);
}
else
{
publishEventArgs.Buffer = buffer;
break;
}
}
PublishEvent?.Invoke(this, publishEventArgs);
}
}
private bool FormStatusIntercept(DevicesSimulator simulatorForm, ref string buffer)
{
string modifiedBuffer = buffer;
//When btnFormStatus button is pressed it changes FormStatusContinued = true
//which allows continuation of the processing by exiting while loop
if (simulatorForm.FormStatusContinued == true)
{
simulatorForm.InvokeEx(form =>
{
if (form.rtbFormStatus.Text != modifiedBuffer)
{
modifiedBuffer = form.rtbFormStatus.Text;
}
form.FormStatusContinued = false;
form.FormStatusInterceptPending = false;
});
buffer = modifiedBuffer;
return false;
}
else if (simulatorForm.FormStatusIntercept == true)
{
if (simulatorForm.FormStatusInterceptPending == false)
{
//Whith check box pressed (true) we request a stop
//and we enter a while loop with Thread.Sleep(1)
simulatorForm.InvokeEx(form =>
{
form.btnFormStatus.Text = "Continue";
form.rtbFormStatus.Text = modifiedBuffer;
form.FormStatusInterceptPending = true;
});
}
return true;
}
return false;
}
https://stackoverflow.com/questions/48777842
复制相似问题