【发布时间】:2018-11-09 07:52:27
【问题描述】:
我正在尝试在这里找到一些解决我的问题的方法,但没有结果(或者我只是没有得到正确的解决方案)所以如果有人可以帮助/解释我将非常感激。
我只是在为使用 Win Form 的系统管理员开发一个工具,现在我需要在后台运行的选定机器上创建一个连续 ping。 UI 上有一个在线状态指示器,我需要使用后台 ping 进行编辑。所以现在我处于这种状态:
A级(获胜形式):
ClassB activeRelation = new ClassB();
public void UpdateOnline(Relation pingedRelation)
{
//There is many Relations at one time, but form shows Info only for one...
if (activeRelation == pingedRelation)
{
if (p_Online.InvokeRequired)
{
p_Online.Invoke(new Action(() =>
p_Online.BackgroundImage = (pingedRelation.Online) ? Properties.Resources.Success : Properties.Resources.Failure
));
}
else
{
p_Online.BackgroundImage = (pingedRelation.Online) ? Properties.Resources.Success : Properties.Resources.Failure;
}
}
}
//Button for tunring On/Off the background ping for current machine
private void Btn_PingOnOff_Click(object sender, EventArgs e)
{
Button btn = (sender is Button) ? sender as Button : null;
if (btn != null)
{
if (activeRelation.PingRunning)
{
activeRelation.StopPing();
btn.Image = Properties.Resources.Switch_Off;
}
else
{
activeRelation.StartPing(UpdateOnline);
btn.Image = Properties.Resources.Switch_On;
}
}
}
B 类(代表与某些机器的关系的类)
private ClassC pinger;
public void StartPing(Action<Relation> action)
{
pinger = new ClassC(this);
pinger.PingStatusUpdate += action;
pinger.Start();
}
public void StopPing()
{
if (pinger != null)
{
pinger.Stop();
pinger = null;
}
}
C类(后台ping类)
private bool running = false;
private ClassB classb;
private Task ping;
private CancellationTokenSource tokenSource;
public event Action<ClassB> PingStatusUpdate;
public ClassC(ClassB classB)
{
this.classB = classB;
}
public void Start()
{
tokenSource = new CancellationTokenSource();
CancellationToken token = tokenSource.Token;
ping = PingAction(token);
running = true;
}
public void Stop()
{
if (running)
{
tokenSource.Cancel();
ping.Wait(); //And there is a problem -> DeadLock
ping.Dispose();
tokenSource.Dispose();
}
running = false;
}
private async Task PingAction(CancellationToken ct)
{
bool previousResult = RemoteTasks.Ping(classB.Name);
PingStatusUpdate?.Invoke(classB);
while (!ct.IsCancellationRequested)
{
await Task.Delay(pingInterval);
bool newResult = RemoteTasks.Ping(classB.Name);
if (newResult != previousResult)
{
previousResult = newResult;
PingStatusUpdate?.Invoke(classB);
}
}
}
所以当我取消令牌和 Wait() 以完成任务时问题处于死锁状态 -> 它仍在运行,但任务中的 While(...) 已正确完成。
【问题讨论】:
-
请提供一个可验证的完整示例。这是太多的代码,而且很有可能,只需制作示例即可解决问题。
-
@Christopher 很抱歉,感谢您的建议,但我真的尝试在这里编写尽可能少的代码。我认为所有这些代码都是解决问题所必需的。但我将尝试删除更多代码。 :)
标签: c# winforms asynchronous task