Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 具有工作线程的WCF服务?_C#_.net_Multithreading_Wcf - Fatal编程技术网

C# 具有工作线程的WCF服务?

C# 具有工作线程的WCF服务?,c#,.net,multithreading,wcf,C#,.net,Multithreading,Wcf,我正在尝试编写一个WCF服务,它将驻留在Windows服务中。此WCF服务将只向列表中添加字符串,然后工作线程将定期处理此列表。实现这一目标的最佳方式是什么?我读过一些相互矛盾的例子,这些例子让我感到困惑。服务和线程共享列表对象的最佳方式是什么 更新: 谢谢你到目前为止的回复。我只是想澄清一下,我不是在为列表的同步或如何使其线程安全而挣扎。所有这些都和我在C++中使用的原理一样。我正在努力解决的是在哪里定义这个列表,以便可以从WCF服务和工作线程访问它。在C++中,我会在全局范围内创建列表,但C

我正在尝试编写一个WCF服务,它将驻留在Windows服务中。此WCF服务将只向列表中添加字符串,然后工作线程将定期处理此列表。实现这一目标的最佳方式是什么?我读过一些相互矛盾的例子,这些例子让我感到困惑。服务和线程共享列表对象的最佳方式是什么

更新: 谢谢你到目前为止的回复。我只是想澄清一下,我不是在为列表的同步或如何使其线程安全而挣扎。所有这些都和我在C++中使用的原理一样。我正在努力解决的是在哪里定义这个列表,以便可以从WCF服务和工作线程访问它。在C++中,我会在全局范围内创建列表,但C语言没有全局范围。如果我在WCF服务类中定义它,线程将看不到它。如果我在服务类(定义并启动线程函数的地方)中定义它,WCF服务将无法看到它。我相信不久前我在ATL做过类似的事情,但现在是周五下午,灰色细胞已经放弃了这一天

更新2: 我应该在哪里定义工作线程?在Windows服务类(即主机)或WCF服务中?WCF服务应该是具有列表成员和线程函数的单例服务吗?这就解决了访问问题。在完成了大量的COM之后,我认为WCF服务是一个COM组件,实例在被访问后就会消亡。这让我想把静态列表和线程函数放在Windows服务类中。对于它来说,这仍然是一个更自然的地方,但也许我只是没有用.NET的方式思考。

1)创建Windows服务

2) WS()中的主机WCF

3) 进行线程同步()


4) 利润

一般模式是在服务启动时启动服务主机。一旦启动,就可以创建工作线程。工作线程和服务调用将需要访问需要同步的共享数据结构。在共享数据对象上设置服务存款项,并发出运行工作线程的信号。工作进程完成后,重置等待句柄的状态

这里有一个快速的小shell,它使用.NET4中的并发集合(在这个例子中,我还使用了.NET4中的任务并行库)。您的问题陈述似乎是不同线程或进程上的典型生产者/消费者,因此这应该让您对如何构建事物有一个合理的想法:

namespace ConcurrentCollectionTest
{
    using System;
    using System.Collections.Concurrent;
    using System.Threading.Tasks;

    internal static class Program
    {
        private static void Main(string[] args)
        {
            ConcurrentQueue<string> cq = new ConcurrentQueue<string>();
            BlockingCollection<string> bc = new BlockingCollection<string>(cq);
            bool moreItemsToAdd = true;

            // Consumer thread
            Task.Factory.StartNew(() =>
            {
                while (!bc.IsCompleted)
                {
                    string s = bc.Take();

                    Console.WriteLine(s);
                }
            });

            // Producer thread
            Task.Factory.StartNew(() =>
            {
                int i = 1;

                while (moreItemsToAdd)
                {
                    bc.Add("string " + i++);
                }

                bc.CompleteAdding();
            });

            // Main Thread
            Console.ReadLine();
            moreItemsToAdd = false;
            Console.ReadLine();
        }
    }
}
命名空间ConcurrentCollectionTest
{
使用制度;
使用System.Collections.Concurrent;
使用System.Threading.Tasks;
内部静态类程序
{
私有静态void Main(字符串[]args)
{
ConcurrentQueue cq=新ConcurrentQueue();
BlockingCollection bc=新BlockingCollection(cq);
bool moreItemsToAdd=true;
//消费线程
Task.Factory.StartNew(()=>
{
而(!bc.已完成)
{
字符串s=bc.Take();
控制台。写入线(s);
}
});
//生产者线程
Task.Factory.StartNew(()=>
{
int i=1;
while(moreItemsToAdd)
{
添加(“字符串”+i++);
}
完成添加();
});
//主线
Console.ReadLine();
moreItemsToAdd=false;
Console.ReadLine();
}
}
}

我认为您具体要求的是,如何将集合实例的引用传递到WCF服务实例中。问题的关键在于:通常情况下,ServiceHost代码将根据服务的InstanceContextMode设置(默认值为PerSession)启动WCF服务实例。这意味着它将根据需要为每个客户端会话启动一个实例。由于主机代码无法直接访问这些自动创建的实例,因此无法注入共享集合

一种解决方案是让您的主机提供一个WCF服务实例,该实例通过构造函数参数或属性设置器添加共享集合。ServiceHost有一个构造函数接受这个实例,但它有一个主要的折衷。这种方法意味着您正在创建一个单例WCF服务(),因此可伸缩性将受到影响。通过设置为multiple,您可以在某种程度上缓解这种情况,但您还必须编写WCF服务代码来处理资源的内部同步

。在C++中,我将在全局范围内创建列表,但C ^没有全局范围。


任何公共静态成员都是全局可见的。当然,您必须实现自己的同步。

您可以在WCF服务的静态构造函数中启动工作线程。当然,不管是
并发模式
还是
InstanceContextMode
,只有一个工作线程。如果这是您想要的,那么下面的代码可能适合您

[ServiceContract]
public interface IYourService
{
  [OperationContract]
  void QueueStringValue(string value);
}

[ServiceBehavior(...)]
public class YourService : IYourService
{
  private static BlockingCollection<string> s_Queue = new BlockingCollection<string>();

  static YourService()
  {
    var thread = new Thread(
      () =>
      {
        while (true)
        {
          string value = s_Queue.Take();
          // Process the string here.
        }
      });
    thread.IsBackground = true;
    thread.Start();
  }

  public void QueueStringValue(string value)
  {
    s_Queue.Add(value);
  }
}
[服务合同]
公共接口服务
{
[经营合同]
无效队列字符串值(字符串值);
}
[服务行为(…)]
公共类YourService:IYourService
{
私有静态BlockingCollection s_队列=新建BlockingCollection();
静态服务()
{
var线程=新线程(
() =>
{
while(true)
{
字符串值=s_Queue.Take();
//在这里处理字符串。
}
});
thread.IsBackground=true;
thread.Start();
}
公共无效队列字符串值(字符串值)
{
添加(值);
}
}
我已经使用生产者-消费者模式来实现工作线程逻辑。
BlockingCollection
类为实现tha提供了一种简单的机制