WPF API可以安全地用在WCF服务中吗? [英] Can the WPF API be safely used in a WCF service?

查看:173
本文介绍了WPF API可以安全地用在WCF服务中吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要使用客户端XAML(来自Silverlight)并创建与服务器端资源(高分辨率图像)合并的位图,并且可以使用WPF(DrawingContext等)轻松地完成此操作。有人提到服务器端(在IIS WCF中托管)使用WPF类似于在服务器上运行Office,这是一个非常糟糕的主意。

I have a requirement to take client side XAML (from Silverlight) and create a bitmap merged with a server side resource (high res image) and can do this quite easily using WPF (DrawingContext etc). It has been mentioned that server side (hosted in IIS WCF) use of WPF is akin to running Office on the server and a really bad idea.

WPF是否构建为运行在服务器上?有哪些替代方案(尤其是xaml)?我需要注意什么(内存泄漏,线程等)?

Is WPF built to run on the server? What are the alternatives (particularly with xaml)? What do I need to look out for (memory leaks, threading etc)?

推荐答案

在WCF后面使用WPF服务器端是相当于运行Office服务器端! WPF作为一个整体只是一些DLL,并且与使用任何其他库服务器端没什么不同。这与完全不同于Word或Excel,您将在后台加载整个应用程序,包括用户界面,加载项,脚本语言等。

Using WPF server-side behind WCF is not equivalent to running Office server-side! WPF as a whole is just a few DLLs, and is really no different than using any other library server-side. This is completely different from Word or Excel, where you are loading an entire application behind the scenes, including user interfaces, add-ins, scripting language, etc.

我多年来一直在WCF背后的服务器上使用WPF。这是一个非常优雅和高效的解决方案:

I have been using WPF on the server behind WCF for years. It is a very elegant and efficient solution:


  • 使用DirectX软件渲染是因为您没有使用实际的显示设备,但是DirectX中的软件渲染例程已经过高度优化,因此您的性能和资源消耗将与您可能找到的任何渲染解决方案一样好,而且可能要好得多。

  • DirectX software rendering is used because you are not drawing on an actual display device, but the software rendering routines in DirectX have been highly optimized so your performance and resource consumption is going to be as good as any rendering solution you might find, and probably much better.

WPF的表现力允许使用优化的DirectX代码创建复杂的图形,而不是手工制作。

WPF's expressivity allows complex graphics to be created using optimized DirectX code rather than doing it by hand.

实际上,在您的WCF服务中使用WPF将为您的RAM足迹增加大约10MB。

Practically speaking, using WPF from within your WCF service will add about 10MB to your RAM footprint.

运行WPF服务器端时,我没有任何内存泄漏问题。我也使用XamlReader将XAML解析为对象树,并且发现当我停止引用对象树时,垃圾收集器会收集它没有问题。我总是认为如果我在WPF中遇到内存泄漏,我会通过在一个单独的AppDomain中运行来解决它,你偶尔会回收它,但我从来没有真正遇到过。

I have not had any memory leak problems with running WPF server-side. I am also using XamlReader to parse XAML into object trees and have found that when I stop referencing the object tree the garbage collector collects it with no problem. I always figured that if I did run into a memory leak in WPF I would work around it by running in a separate AppDomain which you would occasionally recycle, but I never actually encountered one.

您将遇到的一个线程问题是WPF需要STA线程而WCF使用MTA线程。这不是一个重要问题,因为您可以拥有一个STA线程池来获得与MTA线程相同的性能。我写了一个处理转换的STAThreadPool类。这是:

One threading issue you will encounter is that WPF requires STA threads and WCF uses MTA threads. This is not a significant problem since you can have a pool of STA threads to get the same performance as you would from MTA threads. I wrote a little STAThreadPool class that handles the transition. Here it is:

// A simple thread pool implementation that provides STA threads instead of the MTA threads provided by the built-in thread pool
public class STAThreadPool
{
  int _maxThreads;
  int _startedThreads;
  int _idleThreads;
  Queue<Action> _workQueue = new Queue<Action>();

  public STAThreadPool(int maxThreads)
  {
    _maxThreads = maxThreads;
  }

  void Run()
  {
    while(true)
      try
      {
        Action action;
        lock(_workQueue)
        {
          _idleThreads++;
          while(_workQueue.Count==0)
            Monitor.Wait(_workQueue);
          action = _workQueue.Dequeue();
          _idleThreads++;
        }
        action();
      }
      catch(Exception ex)
      {
        System.Diagnostics.Trace.Write("STAThreadPool thread threw exception " + ex);
      }
  }

  public void QueueWork(Action action)
  {
    lock(_workQueue)
    {
      if(_startedThreads < _maxThreads && _idleThreads <= _workQueue.Count)
        new Thread(Run) { ApartmentState = ApartmentState.STA, IsBackground = true, Name = "STAThreadPool#" + ++_startedThreads }.Start();
      _workQueue.Enqueue(action);
      Monitor.PulseAll(_workQueue);
    }
  }

  public void InvokeOnPoolThread(Action action)
  {
    Exception exception = null;
    using(ManualResetEvent doneEvent = new ManualResetEvent(false))  // someday:  Recycle these events
    {
      QueueWork(delegate
      {
        try { action(); } catch(Exception ex) { exception = ex; }
        doneEvent.Set();
      });
      doneEvent.WaitOne();
    }
    if(exception!=null)
      throw exception;
  }

  public T InvokeOnPoolThread<T>(Func<T> func)
  {
    T result = default(T);
    InvokeOnPoolThread(delegate
    {
      result = func();
    });
    return result;
  }
}

这篇关于WPF API可以安全地用在WCF服务中吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆