繁体   English   中英

TCP异步操作期间的AccessViolation

[英]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任务完成(即,一旦客户端连接到服务器),就将处置TcpClientusing (TcpClient c = new TcpClient()) { ... } 之后,您真的不再使用TcpClient对象了吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM