简体   繁体   中英

Generating a PNG from WPF Control in a Windows Service

Due to a rather odd task, I'm wondering whether it is possible to create a Windows Service where, every x seconds we can create the PNG of a System.Windows.Control and write it to disk.

Currently, this process is handled via a WPF app for each user. The process works fine, however the rendering is slow (the controls are large and complicated), and several different versions need to be generated each time. With this in mind, I started wondering whether this could be handled server-side.

So, as an example, say we have a directory containing the following files:

  • Test 1.txt
  • Test 2.txt
  • Test 3.txt

Every 5 seconds, I want to take the name of each of these files, generate a control with the filename as the content, and render to a PNG.

My attempts so far:

  • Service using Timer: Fails with "The calling thread must be STA" even with [STAThread] plastered everywhere
  • DispatcherTimer: Never ticks as there is no UI thread to cause it to tick
  • Service using Timer and Application.Current.Dispatcher.Invoke: Will just crash as there is a null object or two in the call.

Does anyone know if this is even possible?

I'm not sure if you are allowed to create new Windows from a Service. but i can solve your timer problem.

If you want to create one of these timers, the typically need be executed in a STAT-Thread. Why is STAThread required?

Thread timer = new Thread(() =>
{
    while (true)
    {
        //do stuff...

        Thread.Sleep(5000); //wait 5 seconds
    }
 });
 timer.SetApartmentState(ApartmentState.STA); //creates a new Thread for UIs
 timer.IsBackground = true; //if you main Thread exits this will also shutdown.
 timer.Start();

If you don't want to use Lambda

private void MyTimerMethode()
{
    while (true)
    {
        // do stuff...

        Thread.Sleep(5000); //wait 5 seconds
    }
}


    Thread timer = new Thread(MyTimerMethode);
    timer.SetApartmentState(ApartmentState.STA); //creates a new Thread for UIs
    timer.IsBackground = true;
    timer.Start();

If you want to kill it you can use

timer.Abort();

But i recommend using a field like bool isAlive = true; and using it as while loop condition. now if you want to end it you can end it without killing it and throwing any exceptions.

This is what i found after a quick google search for rendering a controls as an image. How to render a WPF UserControl to a bitmap without creating a window

Edit: I've tried using the code from 'How to render a WPF UserControl to a bitmap without creating a window' and it is working even with a Service.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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