在与服务线程不同的线程上运行服务操作
我正在开发一个 WinForms 应用程序,它将包含一个 WebBrowser 并将充当另一个进程的服务。我想实现一个 NavigateAndWait
方法,但显然,当我从客户端调用我的服务(我的 WinForms 应用程序)方法时,此方法在同一线程中运行或以某种方式与服务的 UI 同步运行线。这是我到目前为止所拥有的:
服务:
public class Browser : IBrowser
{
private bool _Navigating = false;
public bool Navigating
{
get { return _Navigating; }
}
public Browser()
{
ServiceForm.Instance.webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser1_DocumentCompleted);
}
void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if(e.Url == ServiceForm.Instance.webBrowser1.Url) _Navigating = false;
}
public void Navigate(string url)
{
_Navigating = true;
ServiceForm.Instance.webBrowser1.Navigate(url);
}
}
客户端:
private void button1_Click(object sender, EventArgs e)
{
EndpointAddress endpointAddress = new EndpointAddress("net.pipe://localhost/PipeReverse/PipeReverse");
NetNamedPipeBinding pipeBinding = new NetNamedPipeBinding();
ChannelFactory<IBrowser> pipeFactory = new ChannelFactory<IBrowser>(pipeBinding, endpointAddress);
IBrowser browser = pipeFactory.CreateChannel();
browser.Navigate("http://www.google.com");
while (browser.Navigating) { }
MessageBox.Show("done!");
}
这工作正常,除了我的客户端会冻结一段时间(字面意思!)。我可以轻松地在客户端的另一个线程上运行 button1_Click
,但我真正想做的是实现我的 NavigateAndWait
(这基本上是最后三行代码在我的服务中的 button1_Click
方法中)。但我已经尝试过了,但它永远不会返回,显然是因为 DocumentComplete
事件处理程序永远不会被调用,因为我位于在服务的 UI 线程中运行的 while
循环内。
所以我的问题是如何告诉 WCF 在 UI 线程以外的线程上运行我的服务操作,以便我可以在该 其他 线程中执行 while
循环?
I'm working on a WinForms application that will contain a WebBrowser
and will act as a service for another process. I'd like to implement a NavigateAndWait
method, but apparently, when I invoke my service's (my WinForms application) methods from the client, this methods run in the same thread or somehow in synchronization with the service's UI thread. This is what I have so far:
Service:
public class Browser : IBrowser
{
private bool _Navigating = false;
public bool Navigating
{
get { return _Navigating; }
}
public Browser()
{
ServiceForm.Instance.webBrowser1.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser1_DocumentCompleted);
}
void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if(e.Url == ServiceForm.Instance.webBrowser1.Url) _Navigating = false;
}
public void Navigate(string url)
{
_Navigating = true;
ServiceForm.Instance.webBrowser1.Navigate(url);
}
}
Client:
private void button1_Click(object sender, EventArgs e)
{
EndpointAddress endpointAddress = new EndpointAddress("net.pipe://localhost/PipeReverse/PipeReverse");
NetNamedPipeBinding pipeBinding = new NetNamedPipeBinding();
ChannelFactory<IBrowser> pipeFactory = new ChannelFactory<IBrowser>(pipeBinding, endpointAddress);
IBrowser browser = pipeFactory.CreateChannel();
browser.Navigate("http://www.google.com");
while (browser.Navigating) { }
MessageBox.Show("done!");
}
This works OK other than my client will freeze for a little while (literally!). I could easily run button1_Click
on another thread in my client, but what I'd really want to do is implement my NavigateAndWait
(which would basically be the last three lines of code in the button1_Click
method) in my service. But I've tried this and it never returns, apparently because the DocumentComplete
event handler never gets called because I'm inside the while
loop running in the service's UI thread.
So my question is how can I tell WCF to run my service's operation on a thread other than the UI thread so I can do my while
loop in that other thread?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您需要在服务的
[ServiceBehavior]
属性中使用UseSynchronizationContext = false
选项。这将告诉 WCF 不要强制将所有请求发布到创建它的线程(在您的情况下为 UI 线程)。该属性将进入服务类(而不是接口)。You need to use the
UseSynchronizationContext = false
option in the[ServiceBehavior]
attribute in your service. That will tell WCF not to enforce the posting of all requests to the thread where it was created (in your case, the UI thread). That attribute would go in the service class (not the interface).