多线程套接字连接挂起c#。套接字超时/挂起

多线程套接字连接挂起c#。套接字超时/挂起,c#,multithreading,sockets,C#,Multithreading,Sockets,我正试图通过套接字连接向两台打印机发送打印指令。脚本工作正常,然后挂起并返回报告: System.IO.IOException:无法将数据写入传输 连接:不允许发送或接收数据的请求,因为 那个方向的插座已经被关闭了 上次关机呼叫 或 System.Net.Sockets.SocketException(0x80004005):由于连接方未正确响应,连接尝试失败 一段时间后,或建立的连接失败,因为 连接的主机无法响应 这个问题是间歇性的,我无法在附加了调试器的情况下重现 有人能发现导致这种行为的原

我正试图通过套接字连接向两台打印机发送打印指令。脚本工作正常,然后挂起并返回报告:

System.IO.IOException:无法将数据写入传输 连接:不允许发送或接收数据的请求,因为 那个方向的插座已经被关闭了 上次关机呼叫

System.Net.Sockets.SocketException(0x80004005):由于连接方未正确响应,连接尝试失败 一段时间后,或建立的连接失败,因为 连接的主机无法响应

这个问题是间歇性的,我无法在附加了调试器的情况下重现

有人能发现导致这种行为的原因吗?我有线程安全问题,我认为这可能是罪魁祸首

为代码量道歉。由于这是线程的可能性,我已经包括了尽可能多的范围,我可以

// main entry point
class HomeController{

    List<string> lsLabelResults = new List<string>("label result");
    PrinterBench pbBench        = new PrinterBench("192.168.2.20","192.168.2.21");

    void Process(){

        oPrintController = new PrintController(this);

        if(GetLabel()){
            // should always come out of the big printer (runs in background)
            oPrintController.PrintBySocketThreaded(lsLabelResults, pbBench.PostageLabelIP);
            // should always come out of the small printer
            oPrintController.PrintWarningLabel();
        }
    }
}

class PrintController{

    HomeController oHC;

    private static Dictionary<string, Socket> lSocks = new Dictionary<string, Socket>();

    private BackgroundWorker _backgroundWorker;
    static readonly object locker = new object();
    double dProgress;
    bool bPrintSuccess = true;


    public PrintController(HomeController oArg_HC)
    {
        oHC = oArg_HC;
    }


    public bool InitSocks()
    {
        // Ensure the IP's / endpoints of users printers are assigned
        if (!lSocks.ContainsKey(oHC.pbBench.PostageLabelIP))
        {
            lSocks.Add(oHC.pbBench.PostageLabelIP, null);
        }
        if (!lSocks.ContainsKey(oHC.pbBench.SmallLabelIP))
        {
            lSocks.Add(oHC.pbBench.SmallLabelIP, null);
        }

        // attempt to create a connection to each socket
        try
        {
            foreach (string sKey in lSocks.Keys.ToList())
            {
                if (lSocks[sKey] == null || !lSocks[sKey].Connected)
                {
                    IPEndPoint ep = new IPEndPoint(IPAddress.Parse(sKey), 9100);
                    lSocks[sKey] = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

                    try
                    {

                        //lSocks[sKey].Connect(ep);
                        var result = lSocks[sKey].BeginConnect(ep, null, null);

                        bool success = result.AsyncWaitHandle.WaitOne(2000, true);
                        // dont need success
                        if (lSocks[sKey].Connected)
                        {
                            lSocks[sKey].EndConnect(result);
                        }
                        else
                        {
                            lSocks[sKey].Close();
                            throw new SocketException(10060); // Connection timed out.
                        }

                    }
                    catch(SocketException se)
                    {
                        if(se.ErrorCode == 10060)
                        {
                            oHC.WriteLog("Unable to init connection to printer. Is it plugged in?", Color.Red);
                        }
                        else
                        {
                            oHC.WriteLog("Unable to init connection to printer. Error: " + se.ErrorCode.ToString(), Color.Red);
                        }
                    }
                    catch (Exception e)
                    {
                        oHC.WriteLog("Unable to init connection to printer. Error: " + e.ToString(), Color.Red);
                    }
                }
            }
        }catch (Exception e)
        {
            oHC.WriteLog(e.ToString(), true);
            return false;
        }

        return true;
    }

    public bool PrintBySocketThreaded(List<string> lsToPrint, string sIP)
    {
        // open both the sockets
        InitSocks();

        bBatchPrintSuccess = false;
        _backgroundWorker = new BackgroundWorker();

        _backgroundWorker.DoWork += new DoWorkEventHandler(backgroundWorker_DoWork);
        _backgroundWorker.RunWorkerCompleted += backgroundWorker_RunWorkerCompleted;
        _backgroundWorker.WorkerReportsProgress = true;
        _backgroundWorker.WorkerSupportsCancellation = true;

        object[] parameters = new object[] { lsToPrint, sIP, lSocks };

        _backgroundWorker.RunWorkerAsync(parameters);
        return true;
    }


    // On worker thread, send to print!
    public void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
    {
        object[] parameters = e.Argument as object[];

        double dProgressChunks = (100 / ((List<string>)parameters[0]).Count);
        int iPos = 1;

        Dictionary<string, Socket> dctSocks = (Dictionary<string, Socket>)parameters[2];

        foreach (string sLabel in (List<string>)parameters[0] )
        {
            bool bPrinted = false;

            // thread lock print by socket to ensure its not accessed twice
            lock (locker)
            {
                // get relevant socket from main thread
                bPrinted = PrintBySocket(sLabel, (string)parameters[1], dctSocks[(string)parameters[1]]);
            }

            iPos++;
        }

        while (!((BackgroundWorker)sender).CancellationPending)
        {
            ((BackgroundWorker)sender).CancelAsync();
            ((BackgroundWorker)sender).Dispose();
            //Thread.Sleep(500);
        }
        return;
    }


    // Back on the 'UI' thread so we can update the progress bar (have access to main thread data)!
    private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Error != null) MessageBox.Show(e.Error.Message);
        if (bPrintSuccess) oHC.WriteLog("Printing Complete");

        bBatchPrintSuccess = true;

        ((BackgroundWorker)sender).CancelAsync();
        ((BackgroundWorker)sender).Dispose();
    }

    /// sends to printer via socket
    public bool PrintBySocket(string sArg_ToPrint, string sIP, Socket sock = null)
    {
        Socket sTmpSock = sock;

        if (sTmpSock == null)
        { 
            InitSocks();

            if (!lSocks.ContainsKey(sIP))
            {
                throw new Exception("Sock not init");
            }
            else
            {
                sTmpSock = lSocks[sIP];
            }
        }

        try
        {

            if(!sTmpSock.Connected || !sTmpSock.IsBound)
            {
                InitSocks();

                if (!sTmpSock.Connected)
                {
                    oHC.WriteLog("Unable to init connection to printer. Is it plugged in?", Color.Red);
                }
            }

            using (NetworkStream ns = new NetworkStream(sTmpSock))
            {
                byte[] toSend = null;

                // convert string to byte stream, or use byte stream
                if (byToPrint == null)
                {
                    toSend = Encoding.ASCII.GetBytes(sEOL + sArg_ToPrint);
                }
                else
                {
                    toSend = byToPrint;
                }

                ns.BeginWrite(toSend, 0, toSend.Length, OnWriteComplete, null);
                ns.Flush();
            }

            return true;

        }
        catch (Exception e)
        {
            oHC.WriteLog("Print by socket: " + e.ToString(), true);
            DisposeSocks();
        }
    }


    public bool PrintWarningLabel()
    {
        string sOut = sEOL + "N" + sEOL;
        sOut += "A0,150,0,4,3,3,N,\"WARNING MESSAGE TO PRINT\"" + sEOL;
        sOut += sEOL;

        if (PrintBySocket(sOut, oHC.pbBench.SmallLabelIP))
        {
            oHC.WriteLog("WARNING LABEL PRINTED");
            return true;
        }
        return false;
    }
}
//主入口点
类家庭控制器{
列表lsLabelResults=新列表(“标签结果”);
PrinterBench pbBench=新的PrinterBench(“192.168.2.20”、“192.168.2.21”);
无效过程(){
oPrintController=新的PrintController(此);
if(GetLabel()){
//应始终从大打印机中打印出来(在后台运行)
PrintBySocketThreaded(lsLabelResults、pbBench.PostageLabelIP);
//应始终从小型打印机中打印出来
oPrintController.PrintWarningLabel();
}
}
}
类打印控制器{
家庭控制器;
私有静态字典lSocks=新字典();
私人后台人员(u后台人员);
静态只读对象锁定器=新对象();
双D进程;
bool bPrintSuccess=true;
公共打印控制器(HomeController oArg_HC)
{
oHC=Oag_HC;
}
公共bool InitSocks()
{
//确保已分配用户/打印机的IP/端点
如果(!lSocks.ContainsKey(oHC.pbBench.PostageLabelIP))
{
lSocks.Add(oHC.pbBench.PostageLabelIP,null);
}
如果(!lSocks.ContainsKey(oHC.pbBench.SmallLabelIP))
{
lSocks.Add(oHC.pbBench.SmallLabelIP,null);
}
//尝试创建到每个套接字的连接
尝试
{
foreach(lSocks.Keys.ToList()中的字符串sKey)
{
if(lSocks[sKey]==null | |!lSocks[sKey].已连接)
{
IPEndPoint ep=新的IPEndPoint(IPAddress.Parse(sKey),9100);
lSocks[sKey]=新套接字(ep.AddressFamily,SocketType.Stream,ProtocolType.Tcp);
尝试
{
//lSocks[sKey].Connect(ep);
var result=lSocks[sKey].BeginConnect(ep,null,null);
bool success=result.AsyncWaitHandle.WaitOne(2000,true);
//不需要成功
if(lSocks[sKey].已连接)
{
lSocks[sKey].EndConnect(结果);
}
其他的
{
lSocks[sKey].Close();
抛出新的SocketException(10060);//连接超时。
}
}
捕获(SocketException se)
{
如果(se.ErrorCode==10060)
{
oHC.WriteLog(“无法初始化与打印机的连接。是否已插入?”,颜色为红色);
}
其他的
{
oHC.WriteLog(“无法初始化与打印机的连接。错误:+se.ErrorCode.ToString(),Color.Red”);
}
}
捕获(例外e)
{
oHC.WriteLog(“无法初始化与打印机的连接。错误:+e.ToString(),Color.Red”);
}
}
}
}捕获(例外e)
{
oHC.WriteLog(例如ToString(),true);
返回false;
}
返回true;
}
public bool PrintBySocketThreaded(列表lsToPrint,字符串sIP)
{
//打开两个插座
InitSocks();
bBatchPrintSuccess=false;
_backgroundWorker=新的backgroundWorker();
_backgroundWorker.DoWork+=新的DoworkerVenthandler(backgroundWorker_DoWork);
_backgroundWorker.RunWorkerCompleted+=backgroundWorker\u RunWorkerCompleted;
_backgroundWorker.WorkerReportsProgress=true;
_backgroundWorker.WorkerSupportsScanCellation=true;
对象[]参数=新对象[]{lsToPrint,sIP,lSocks};
_backgroundWorker.RunWorkerAsync(参数);
返回true;
}
//在工作线程上,发送以打印!
public void backgroundWorker_DoWork(对象发送方,DoWorkEventArgs e)
{
对象[]参数=e.参数作为对象[];
双dProgressChunks=(100/((列表)参数[0]).Count);
int iPos=1;
Dictionary=(Dictionary)参数[2];
foreach(列表参数[0]中的字符串sLabel)
{
bool bPrinted=假;
//通过插座螺纹锁定打印,确保其不会被访问两次
锁(储物柜)
{
//从主线程获取相关套接字
bPrinted=PrintBySocket(sLabel,(string)参数[1],dctSocks[(string)参数[1]];
}
iPos++;
}
while(!((BackgroundWorker)发件人)。取消挂起)
{
((BackgroundWorker)发送方).CancelAsync();
((BackgroundWorker)发送方).Dispose();
//睡眠(500);
}
R
static class NetworkPrinter
{
    const ushort tcpPort = 31337;
    const string sEOL = "\r\n";

    /// <summary>Send a single job to the printer.</summary>
    static async Task sendLabel( Stream stream, string what, CancellationToken ct )
    {
        byte[] toSend = Encoding.ASCII.GetBytes( sEOL + what );
        await stream.WriteAsync( toSend, 0, toSend.Length, ct );
        await stream.FlushAsync();
    }

    /// <summary>Connect to a network printer, send a batch of jobs reporting progress, disconnect.</summary>
    public static async Task printLabels( string ip, string[] labels, Action<double> progress, CancellationToken ct )
    {
        IPAddress address = IPAddress.Parse( ip );
        double progressMul = 1.0 / labels.Length;
        using( var tc = new TcpClient() )
        {
            await tc.ConnectAsync( address, tcpPort );
            Stream stream = tc.GetStream();
            for( int i = 0; i < labels.Length; )
            {
                ct.ThrowIfCancellationRequested();
                await sendLabel( stream, labels[ i ], ct );
                i++;
                progress( i * progressMul );
            }
        }
    }

    /// <summary>Send multiple batches to multiple printers, return true of all of them were good.</summary>
    public static async Task<bool> printBatches( LabelBatch[] batches )
    {
        await Task.WhenAll( batches.Select( a => a.print( CancellationToken.None ) ) );
        return batches.All( a => a.completed );
    }
}

/// <summary>A batch of labels to be printed by a single printer.</summary>
/// <remarks>Once printed, includes some status info.</remarks>
class LabelBatch
{
    readonly string ip;
    readonly string[] labels;
    public bool completed { get; private set; } = false;
    public Exception exception { get; private set; } = null;

    public LabelBatch( string ip, IEnumerable<string> labels )
    {
        this.ip = ip;
        this.labels = labels.ToArray();
    }

    /// <summary>Print all labels, ignoring the progress. This method doesn't throw, returns false if failed.</summary>
    public async Task<bool> print( CancellationToken ct )
    {
        completed = false;
        exception = null;
        try
        {
            await NetworkPrinter.printLabels( ip, labels, d => { }, ct );
            completed = true;
        }
        catch( Exception ex )
        {
            exception = ex;
        }
        return completed;
    }
}