Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/313.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# TcpClient.ConnectAsync或Socket.BeginConnect具有非阻塞超时设置_C#_.net_Sockets_Task Parallel Library_Async Await - Fatal编程技术网

C# TcpClient.ConnectAsync或Socket.BeginConnect具有非阻塞超时设置

C# TcpClient.ConnectAsync或Socket.BeginConnect具有非阻塞超时设置,c#,.net,sockets,task-parallel-library,async-await,C#,.net,Sockets,Task Parallel Library,Async Await,到目前为止,我找到的所有解决方案都基于WaitOne: 或 对我来说,用WaitOne阻塞线程会破坏异步方法的用途。生成另一个线程并不是更好(因为异步模型努力使用尽可能少的线程) 有没有其他解决方案可以让我在不阻塞当前线程或生成另一个线程的情况下中止连接尝试 我正在开发一个由外部代码使用的库,它不知道我的库中发生了什么(代码只调用我的ConnectAsync方法,其余的都由我来完成,包括TcpClient.ConnectAsync等等)。外部代码可以是任何东西(web应用程序、桌面应用程序、Wi

到目前为止,我找到的所有解决方案都基于WaitOne: 或

对我来说,用
WaitOne
阻塞线程会破坏异步方法的用途。生成另一个线程并不是更好(因为异步模型努力使用尽可能少的线程)

有没有其他解决方案可以让我在不阻塞当前线程或生成另一个线程的情况下中止连接尝试


我正在开发一个由外部代码使用的库,它不知道我的库中发生了什么(代码只调用我的ConnectAsync方法,其余的都由我来完成,包括
TcpClient.ConnectAsync
等等)。外部代码可以是任何东西(web应用程序、桌面应用程序、Windows服务等)。理想情况下,解决方案不需要外部代码执行任何操作来中止我的类的setting.Timeout属性之外的操作。但是,如果这是实现自定义连接超时时避免阻塞或工作线程的唯一方法,我将很高兴看到我有哪些选项(在异步/等待模型方面)。

如果您为超时创建第二个任务(做得很好),那么您可以在任务或超时完成后立即使用来完成

var timeout = Task.Delay(whatever);
var mightTimeout = Task.WhenAny(new {} { timeout, originalTask });

// let mightTimeout complete by whatever method (eg. async)

if (mightTimeout == timeout) {
  // Timeout!!
  // Put abort code in here.
}

TcpClient.SendAsync
没有收到
CancellationToken
因此它不能真正被取消()。您可以使用
with timeout
扩展方法:

public static Task<TResult> WithTimeout<TResult>(this Task<TResult> task, TimeSpan timeout)
{
    var timeoutTask = Task.Delay(timeout).ContinueWith(_ => default(TResult), TaskContinuationOptions.ExecuteSynchronously);
    return Task.WhenAny(task, timeoutTask).Unwrap();
}

我找到了一个解决方案

等待任务

Task.WhenAny将在包含的任何任务首先完成时完成。 将其放入异步函数中

下面是一个适合我的例子:

Public Async Function TCPConnectionAsync(HostIpAddress, Port) As Task(Of String)
 Dim client As New TcpClient     
  Await Task.WhenAny(client.ConnectAsync(HostIpAddress, Porta), Task.Delay(3000)) 
 'this above will not block because function is async,
 'whenever the connection is successful or Task.Delay expires the task will end
 ' proceeding next, where you can check the connection 


 If client.Connected = False Then 'this will be evaluated after 3000ms
      client.Close()
      return "not connected"
 else
      'do here whatever you need with the client connection


       client.Close()
       return "all done"
 End If
End Sub

我想我这里的问题()是重复的。但我不想愚弄它,那不会使任何事情流产。你可能想在某个地方加入一个
取消令牌
。@Jeroenmoster是真的,但这并不是这里真正有趣的一点。如果你在生产代码中加入这个,然后收到人们的投诉,说你的应用程序使机器的端口用完了,那么它很快就会变得非常有趣。。。这种方法通常是可用的,但前提是您要记住,没有任何东西真的被中止了,并且您不能不考虑这一点就开始新的操作。@Jeroenmoster我不是说端口没有关闭。谢谢,这很有帮助。我不能“使用”块,因为我的方法只连接(我不控制连接的整个生命周期),但在这里它并不重要。
ObjectDisposedException
应该是
NullReferenceException
。请参阅:不要调用<代码> TCPclient。Debug < /C> >考虑“<代码> TCPclient .Client”关闭>代码>。这会关闭连接,导致原始操作在不引发异常的情况下完成。然后可以安全地处置
TcpClient
Public Async Function TCPConnectionAsync(HostIpAddress, Port) As Task(Of String)
 Dim client As New TcpClient     
  Await Task.WhenAny(client.ConnectAsync(HostIpAddress, Porta), Task.Delay(3000)) 
 'this above will not block because function is async,
 'whenever the connection is successful or Task.Delay expires the task will end
 ' proceeding next, where you can check the connection 


 If client.Connected = False Then 'this will be evaluated after 3000ms
      client.Close()
      return "not connected"
 else
      'do here whatever you need with the client connection


       client.Close()
       return "all done"
 End If
End Sub