현재 실행중인 경우 백그라운드 작업자를 취소하고 다른 작업을 시작하려고합니다. 작업자가이 후 StartServerGetIP.RunWorkerAsync();
차단 배경 작업자 및 Application.DoEvents에
에 취소되면
이 난에 못생긴 해결책을 발견 ... 함수에서 취소를 더 검사가 먼저private void StartWorker()
{
if (StartServerGetIP.IsBusy) { StartServerGetIP.CancelAsync(); }
StartServerGetIP.RunWorkerAsync();
}
private void StartServerGetIP_DoWork(object sender, DoWorkEventArgs e)
{
StartFTPServer(Port, Ringbuf, sender as BackgroundWorker, e);
if ((sender as BackgroundWorker).CancellationPending) return;
GetIP(Ringbuf, sender as BackgroundWorker, e);
}
private void StartServerGetIP_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
return;
}
if (e.Result.ToString() == "Faulted")
{
tcs.SetResult(false);
return;
}
Client.IPAddress = e.Result.ToString();
tcs.SetResult(true);
}
이 접근 블록이 시도
private void StartWorker()
{
if (StartServerGetIP.IsBusy) { StartServerGetIP.CancelAsync(); }
while(StartServerGetIP.IsBusy) { Application.DoEvents(); }
StartServerGetIP.RunWorkerAsync();
}
인가가 나는를 호출하지 않고 그 날이 비동기 배경 노동자를 취소하고 다른 시작 할 수 있도록 구현할 수있는 패턴?
편집 : 취소 버튼은 문제가되지 않습니다.
편집 :
private void StartFTPServer(SerialPort port, RingBuffer<string> buffer, BackgroundWorker sender, DoWorkEventArgs args)
{
Stopwatch timeout = new Stopwatch();
TimeSpan max = TimeSpan.FromSeconds(MaxTime_StartServer);
int time_before = 0;
timeout.Start();
while (!buffer.Return.Contains("Run into Binary Data Comm mode...") && timeout.Elapsed.Seconds < max.Seconds)
{
if (timeout.Elapsed.Seconds > time_before)
{
time_before = timeout.Elapsed.Seconds;
sender.ReportProgress(CalcPercentage(max.Seconds, timeout.Elapsed.Seconds));
}
if (sender.CancellationPending)
{
args.Cancel = true;
return;
}
}
port.Write("q"); //gets into menu
port.Write("F"); //starts FTP server
}
private void GetIP(RingBuffer<string> buffer, BackgroundWorker sender, DoWorkEventArgs args)
{
//if longer than 5 seconds, cancel this step
Stopwatch timeout = new Stopwatch();
TimeSpan max = TimeSpan.FromSeconds(MaxTime_GetIP);
timeout.Start();
int time_before = 0;
string message;
while (!(message = buffer.Return).Contains("Board IP:"))
{
if (timeout.Elapsed.Seconds > time_before)
{
time_before = timeout.Elapsed.Seconds;
sender.ReportProgress(CalcPercentage(max.Seconds, timeout.Elapsed.Seconds + MaxTime_StartServer));
}
if (timeout.Elapsed.Seconds >= max.Seconds)
{
args.Result = "Faulted";
return;
}
if (sender.CancellationPending)
{
args.Cancel = true;
return;
}
}
Regex regex = new Regex(@"\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b");
string IP = message.Remove(0, "Board IP: ".Length);
if (regex.IsMatch(IP))
{
args.Result = IP;
ServerAlive = true;
}
}
뿐만 아니라 당신의 StartServerGetIP_DoWork 방법에 .. 너무 당신에게
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace FPGAProgrammerLib
{
class RingBuffer<T>
{
T [] buffer { get; set; }
int _index;
int index
{
get
{
return _index;
}
set
{
_index = (value) % buffer.Length;
}
}
public T Add
{
set
{
buffer[index++] = value;
}
}
public T Return
{
get
{
return (index == 0) ? (IsString() ? (T)(object)string.Empty : default(T)) : buffer[--index];
}
}
private bool IsString()
{
return (typeof(T) == typeof(string) || (typeof(T) == typeof(String)));
}
public RingBuffer(int size)
{
buffer = new T[size];
index = 0;
}
}
}
적) ('Application.DoEvents를 사용하지 마십시오 '. 그것은 위험으로 가득차 있습니다. 매우 조심 스럽거나 운이 좋으면 코드에서 오류를 디버그하는 것이 매우 어려워집니다. VB6 업그레이드를위한 이전 버전과의 호환성을 위해서만 프레임 워크에 있습니다. – Enigmativity
이것을 수행하는 훨씬 좋은 방법이 있습니다. 전체 코드를 게시 할 수 있습니까? 귀하의 코드를 복사, 붙여 넣기 및 실행할 수 있기를 바랍니다. – Enigmativity
당신이 지금하고있는 방식은 항상 * 근본적인 경주입니다. CancelAsync()가 실제로 tcs.Result가 설정되지 않는다고 보장 할 수는 없습니다. Undebuggable뿐만 아니라, 이것은 일주일에 한 번 잘못됩니다. StartWorker()를 실패하거나 절대로 호출 할 수 없도록 올바른 솔루션을 제안 할 수있는 코드가 충분하지 않습니다. –