[英]AccessViolation during async TCP operations
在各种异步TCP操作期间,我不断收到未处理的AccessViolationException
。 仅在内置函数System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
中的“反汇编”窗口中才会出现该异常。 异常的堆栈跟踪仅包含此功能。 组装线是: cmp dword ptr [ecx], ecx
。
最令人烦恼的是异常会不定期地到达(程序可以在其之前执行30分钟,6小时或15秒)。
这是完整的异常描述:
System.AccessViolationException unhandled
HResult=-2147467261
Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Source=mscorlib
StackTrace:
in System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
InnerException:
代码:在以任何方式访问TCP套接字异步的任何尝试期间,我都遇到了此异常。 我不使用外部非托管代码。 这是我最后一次异步连接到远程地址组的尝试。
class Program
{
static void Main(string[] args)
{
PollerCore p = new PollerCore();
p.Start();
Console.ReadLine();
}
}
public class PollerCore
{
string[] ip = new string[255];
public void Start()
{
for (int i = 1; i < 255; i++)
{
ip[i] = String.Format("192.168.100.{0}", i);
}
new Thread(WorkerThread).Start();
}
async void WorkerThread()
{
while (true)
{
Console.WriteLine("In wt... ");
DateTime dt = DateTime.Now;
List<Task<string>> tasks = new List<Task<string>>();
foreach (string addr in ip)
{
if (String.IsNullOrEmpty(addr)) continue;
tasks.Add(ConnectToDevice(addr));
}
string[] res = await Task.WhenAll(tasks.ToArray());
foreach (string s in res)
{
if (s != null) Console.WriteLine("Connecting to {0}... DONE", s);
}
Thread.Sleep(100);
}
}
async Task<string> ConnectToDevice(string ip)
{
using (TcpClient c = new TcpClient())
{
try
{
await c.ConnectAsync(ip, 5100);
return ip;
}
catch
{
return null;
}
}
}
}
更新:根据Noseratio建议重新编写了代码中引发的相同异常。 Thread.Start已替换为Task.Run。 在
catch
{
return null;
}
我只收到代码为10060(Timeout)的SocketExceptions ...
我认为问题可能在这里:
new Thread(WorkerThread).Start();
// ...
async void WorkerThread()
{
// ...
}
尝试将其更改为此:
var task = Task.Run(() => WorkerThreadAsync());
task.Wait(); // for debugging
// ...
async Task WorkerThreadAsync()
{
// ...
}
另外,根本不要使用单独的线程:
var task = WorkerThreadAsync();
task.Wait(); // for debugging
无论如何,您都在WorkerThread
使用了异步API,最有可能在第一次await
之后切换到另一个池线程。
还有几件事:
catch { return null }
。 转储实际的异常信息。 ConnectAsync
任务完成(即,一旦客户端连接到服务器),就将处置TcpClient
: using (TcpClient c = new TcpClient()) { ... }
。 之后,您真的不再使用TcpClient
对象了吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.