在与服务线程不同的线程上运行服务操作

发布于 2024-12-11 16:54:46 字数 1835 浏览 1 评论 0原文

我正在开发一个 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

汐鸠 2024-12-18 16:54:46

您需要在服务的 [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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文