从同一任务的"继续使用"方法启动任务是否安全?



我有一个带有侦听器的Windows服务,该侦听器在侦听ServiceBus的任务中运行循环。如果连接断开或出现其他问题,我想再次启动侦听器任务。由于我没有对任务执行任何等待操作,因为它应该永远运行,因此我确实需要使用ContinueWith并检查是否发生了异常。如果是这样,我想开始完全相同的过程。

所以问题是:对于执行上下文、内存、堆栈跟踪或其他一些我没有考虑过的事情,这样做是否安全?

代码似乎运行良好,如果网络关闭并重新上线,则重新连接,异常的堆栈跟踪似乎也是正确的,但我担心一些我没有想到的陷阱。

private void StartReceiving(string connectionString)
{
_receiverHost
.StartReceiving(connectionString)
.ContinueWith(c =>
{
if (c.IsFaulted)
{
Thread.Sleep(60000);
StartReceiving(connectionString);
}
}
});

}

回答您的问题:

"对于执行上下文、内存、堆栈跟踪或其他一些我没有考虑过的事情,这样做是否安全?">

是的;我能想到的任何提到的领域都没有问题。 您基本上退出上一个任务并输入一个新任务。当您继续执行以下任务并且堆栈跟踪在创建执行的任务处启动时,您的内存将被清理。

但是,我宁愿评论它在错误处理和中断执行方面引入的问题,通过此实现,这并不能帮助您找到错误,连接到备用地址或您可能引入的其他逻辑。在我看来,您在此实现中引入了意想不到的复杂性。

如果我必须实现这个类,我宁愿引发一个断开连接的事件,使用该对象的类必须解决该事件。这将为您提供更广泛的机会,例如通知其他依赖类。

此外,冻结线程通常不是一个好的解决方案。我宁愿启动计时器或类似的东西。

我在一些额外的代码中尝试了您的代码,如下所示,但我看不到执行上下文、内存、堆栈跟踪的任何问题。

public class Receiver
{
public async Task StartReceiving(string connectionString)
{
var task = Task.Run(() =>
{
try
{
throw new Exception("connection lost");
}
catch (Exception)
{
/* log the exception, or something */
throw;
}
});
await task;
}
}
public class Server
{
ILog log = LogManager.GetLogger<Server>();
public bool IsStopped { get; private set; } = false;
private Receiver _receiverHost = new Receiver();
public void StartReceiving(string connectionString)
{
_receiverHost
.StartReceiving(connectionString)
.ContinueWith(async c =>
{
if (c.IsFaulted)
{
var n = Process.GetCurrentProcess().Threads.Count;
var timestamp = DateTime.UtcNow;
await Task.Delay(1000);
log.Debug($"Task Delay: {(DateTime.UtcNow - timestamp).TotalSeconds} seconds");
StartReceiving(connectionString);
}
});
}
}
[TestFixture]
public class TestServerRetry
{
[TestCase]
public async Task TestRetry()
{
var server = new Server();
server.StartReceiving("test connection");
while (!server.IsStopped)
await Task.Delay(100);
}
}

最新更新