c#螺纹安全套筒混淆

c#螺纹安全套筒混淆,c#,multithreading,thread-safety,C#,Multithreading,Thread Safety,我认为这是一个线程安全问题 我有两台打印机,一台装有小标签,另一台装有大标签。我想通过插座向每台打印机发送一份打印作业 我已尝试对第一个请求(大标签)进行线程/后台处理,因为它可能需要很长时间才能完成 脚本按预期工作的99%时间。小标签和大标签分别来自各自的打印机 但是,有时大小标签都会被发送到同一台打印机!无论是小的还是大的 我认为这与线程安全有关,但我发现很难追踪和理解发生了什么。我曾尝试在使用后添加锁并关闭插座,但无论我如何尝试,问题仍然存在 我已经尝试将我的代码减少到最低限度,但我知道这

我认为这是一个线程安全问题

我有两台打印机,一台装有小标签,另一台装有大标签。我想通过插座向每台打印机发送一份打印作业

我已尝试对第一个请求(大标签)进行线程/后台处理,因为它可能需要很长时间才能完成

脚本按预期工作的99%时间。小标签和大标签分别来自各自的打印机

但是,有时大小标签都会被发送到同一台打印机!无论是小的还是大的

我认为这与线程安全有关,但我发现很难追踪和理解发生了什么。我曾尝试在使用后添加锁并关闭插座,但无论我如何尝试,问题仍然存在

我已经尝试将我的代码减少到最低限度,但我知道这篇文章的代码仍然非常繁重。如有任何建议,将不胜感激

// stores the printer info
class PrinterBench
{
    public PrinterBench(string sArg_PostageLabelIP, string sArg_SmallLabelIP)
    {
        PostageLabelIP = sArg_PostageLabelIP;
        SmallLabelIP = sArg_SmallLabelIP;
    }
    public string PostageLabelIP;
    public string SmallLabelIP;
}

// main entry point
class HomeController{

    PrintController oPrintController;
    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;
    public EndPoint ep { get; set; }
    public Socket sock { get; set; }
    public NetworkStream ns { get; set; }

    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
        foreach (string sKey in lSocks.Keys.ToList())
        {
            if (lSocks[sKey] == null || !lSocks[sKey].Connected )
            {
                ep = new IPEndPoint(IPAddress.Parse(sKey), 9100);
                lSocks[sKey] = new Socket(ep.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
                lSocks[sKey].Connect(ep);
            }
        }
        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];
            }
        }

        using (ns = new NetworkStream(sTmpSock))
        {
            byte[] toSend = Encoding.ASCII.GetBytes(sEOL + sArg_ToPrint);
            ns.BeginWrite(toSend, 0, toSend.Length, OnWriteComplete, null);
            ns.Flush();
        }
        return true;
    }


    public bool PrintWarningLabel()
    {
        string sOut = sEOL + "N" + sEOL;
        sOut += "LL411" + sEOL;
        sOut += "R40,0" + sEOL;
        sOut += "S5" + sEOL;
        sOut += "D15" + sEOL;
        sOut += "A0,0,0,4,4,3,N,\"!!!!!!!!!!!!!!!!!!!!!!!\"" + sEOL;
        sOut += "A0,150,0,4,3,3,N,\"WARNING MESSAGE TO PRINT\"" + sEOL;
        sOut += "A0,280,0,4,4,3,N,\"!!!!!!!!!!!!!!!!!!!!!!!\"" + sEOL;
        sOut += "P1";
        sOut += sEOL;

        if (PrintBySocket(sOut, oHC.pbBench.SmallLabelIP))
        {
            oHC.WriteLog("WARNING LABEL PRINTED");
            return true;
        }
        return false;
    }
}
//存储打印机信息
类PrinterBench
{
公共打印机边界(字符串sArg_postageliblip,字符串sArg_SmallLabelIP)
{
PostageLabelIP=特区政府PostageLabelIP;
SmallLabelIP=sArg_SmallLabelIP;
}
公共字符串postagelip;
公共字符串SmallLabelIP;
}
//主要入口点
类家庭控制器{
打印控制器;
列表lsLabelResults=新列表(“标签结果”);
PrinterBench pbBench=新的PrinterBench(“192.168.2.20”、“192.168.2.21”);
无效过程(){
oPrintController=新的PrintController(此);
if(GetLabel()){
//应始终从大打印机中打印出来(在后台运行)
PrintBySocketThreaded(lsLabelResults、pbBench.PostageLabelIP);
//应始终从小型打印机中打印出来
oPrintController.PrintWarningLabel();
}
}
}
类打印控制器{
家庭控制器;
公共端点ep{get;set;}
公共套接字sock{get;set;}
公用网络流ns{get;set;}
私有静态字典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].已连接)
{
ep=新的IPEndPoint(IPAddress.Parse(sKey),9100);
lSocks[sKey]=新套接字(ep.AddressFamily,SocketType.Stream,ProtocolType.Tcp);
lSocks[sKey].Connect(ep);
}
}
返回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);
}
返回;
}
//回到“UI”线程,这样我们就可以更新进度条(可以访问主线程数据)!
私有void backgroundWorker_RunWorkerCompleted(对象发送方,runworkercompletedeventarge)
{
if(e.Error!=null)MessageBox.Show(e.Error.Message);
如果(bPrintSuccess)oHC.WriteLog(“打印完成”);
bBatchPrintSuccess=true;
((BackgroundWorker)发送方).CancelAsync();
((BackgroundWorker)发送方).Dispose();
}
///通过套接字发送到打印机
public bool PrintBySocket(字符串sArg\u ToPrint,字符串sIP,套接字sock=null)
{
Socket sTmpSock=sock;
如果(sTmpSock==null)
{ 
InitSocks();
如果(!lSocks.ContainsKey(sIP)){
抛出新异常(“Sock not init”);
}否则{
sTmpSock=lSocks[sIP];
}
}
使用(ns=新网络流(sTmpSock))
{
byte[]toSend=Encoding.ASCII.GetBytes(sEOL+sArg\u ToPrint);
ns.BeginWrite(toSend,0,toSend.Length,OnWriteComplete,null);
ns.Flush();
}
返回true;
}
公共布尔打印警告标签()
{
public NetworkStream ns { get; set; }
    using (ns = new NetworkStream(sTmpSock))
    {
        byte[] toSend = Encoding.ASCII.GetBytes(sEOL + sArg_ToPrint);
        ns.BeginWrite(toSend, 0, toSend.Length, OnWriteComplete, null);
        ns.Flush();
    }
using (var ns = new NetworkStream(sTmpSock))