Windows服务:调用线程无法访问此对象,因为另一个线程拥有它

时间:2013-04-22 11:25:45

标签: c# windows multithreading service timer

尝试使用XSL转换XML文件并打印输出。但是,收到以下消息:调用线程无法访问此对象,因为另一个线程拥有它。

要设置检查文件的间隔,请在OnStart中添加一个计时器。

            if (findPrinter() > 0)
            {
                System.Timers.Timer printNetterCheck = new System.Timers.Timer();
                printNetterCheck.Elapsed += new ElapsedEventHandler(OnTimedEvent);

                printNetterCheck.Interval = 30000;
                printNetterCheck.Enabled = true;
            }

OnTimedEvent:

    private void OnTimedEvent(object source, ElapsedEventArgs e)
    {            
        getFiles();
    }

如果有任何可用文件,请致电打印:

            foreach (string file in files)
            {
                try
                {
                    StringWriter xslTransformResult = new StringWriter();
                    XslCompiledTransform xslt = new XslCompiledTransform();
                    xslt.Load(xslPath);
                    xslt.Transform(file, null, xslTransformResult);

                    if (print(xslTransformResult) == 1)
                    {
                              //do some things

打印功能:

    private int print(StringWriter transformedXML)
    {
        //assume OK
        int rc = 1;

        try
        {
            StringReader printNetterStreamReader = new StringReader(transformedXML.ToString());
            PrintSystemJobInfo printNetterJob = printer.AddJob("PrintNetterPrint");

            Stream printNetterStream = printNetterJob.JobStream;


            Byte[] printNetterByteBuffer = UnicodeEncoding.Unicode.GetBytes(printNetterStreamReader.ReadToEnd());

            printNetterStream.Write(printNetterByteBuffer, 0, printNetterByteBuffer.Length);
            printNetterStream.Close();
        }
        catch (Exception e)
        {
            //return fail
            rc = -1;
            eventLog.WriteEntry("Error printing: " + e.Message, EventLogEntryType.Error);
        }

        return rc;

    }

调用print时,我收到线程错误。找到了一些关于Dispatchers等的东西..但是在使用服务时这些都没有。

2 个答案:

答案 0 :(得分:1)

检查PrintQueue.AddJob

该方法进行COM调用,该调用要求应用程序在单个单元(STA)中运行。解决这个问题的最简单方法是将STAThreadAttribute添加到Main,这会强制应用程序在单个线程中运行。如果您的应用程序中需要多线程,那么您需要实现必要的管道以在PrintQueue STA上单独运行Thread

// Create a factory to hold your printer configuration
// So that it can be retrieved on demand
// You might need to move the findPrinter() logic
public class PrintQueueFactory
{
    private static PrintQueue _instance = new PrinterQueue(/* Details */);

    public static PrintQueue PrintQueue { get { return _instance; } }
}

private int print(StringWriter transformedXML)
{
    //assume OK
    int rc = 1;

    try
    {
        var printer = PrintQueueFactory.PrintQueue;
        var staThread = new Thread(() => Print(printer, transformedXML.ToString()));
        staThread.SetApartmentState(ApartmentState.STA);
        staThread.Start();
        staThread.Join();
    }
    catch (Exception e)
    {
        //return fail
        rc = -1;
        eventLog.WriteEntry("Error printing: " + e.Message, EventLogEntryType.Error);
    }

    return rc;

}

private static void Print(PrintQueue printer, string lines)
{
    using(var printNetterJob = printer.AddJob("PrintNetterPrint"))
    using(var printNetterStreamReader = new StringReader(lines))
    using(var printNetterStream = printNetterJob.JobStream)
    {
        Byte[] printNetterByteBuffer = UnicodeEncoding.Unicode.GetBytes(printNetterStreamReader.ReadToEnd());
        printNetterStream.Write(printNetterByteBuffer, 0, printNetterByteBuffer.Length);
    }
}

答案 1 :(得分:0)

也许,因为你正在使用Timer控件,它与多线程有关,也许你应该检查Timer.Elapsed事件处理程序中是否需要Invoke(InvokeRequired)。

如果是这样,你应该创建一个委托来调用这个函数,这样它就可以在正确的线程中执行。

Check this Invoke-Required question

相关问题