首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在C#中同步包装异步方法

在C#中同步包装异步方法
EN

Stack Overflow用户
提问于 2009-01-24 06:20:00
回答 4查看 6.6K关注 0票数 8

我有一个第三方库,其中包含一个异步执行函数的类。该类继承自窗体。该函数基本上基于存储在数据库中的数据执行计算。一旦完成,它将调用调用窗体中的_Complete事件。

我想要做的是从非windows窗体应用程序同步调用该函数。问题是,无论我做什么,我的应用程序块和_Complete事件处理程序都不会触发。在windows窗体中,我可以使用"complete“标志和"while (!complete) application.doevents”来模拟同步运行的函数,但显然application.doevents在非windows窗体应用程序中不可用。

有没有什么东西会阻止我在windows窗体应用程序之外使用这个类的方法(因为它是从‘form’继承的)?有什么办法可以解决这个问题吗?

谢谢,迈克

EN

回答 4

Stack Overflow用户

发布于 2009-01-24 06:46:59

在一次尝试中,可能值得尝试下面这样的方法,它使用WaitHandle来阻塞当前线程,而不是旋转和检查标志。

代码语言:javascript
运行
复制
using System;
using System.Threading;

class Program
{
    AutoResetEvent _autoEvent;

    static void Main()
    {
        Program p = new Program();
        p.RunWidget();
    }

    public Program()
    {
        _autoEvent = new AutoResetEvent(false);
    }

    public void RunWidget()
    {
        ThirdParty widget = new ThirdParty();           
        widget.Completed += new EventHandler(this.Widget_Completed);
        widget.DoWork();

        // Waits for signal that work is done
        _autoEvent.WaitOne();
    }

    // Assumes that some kind of args are passed by the event
    public void Widget_Completed(object sender, EventArgs e)
    {
        _autoEvent.Set();
    }
}
票数 8
EN

Stack Overflow用户

发布于 2009-01-28 02:47:17

我有更多关于这个问题的信息(我和mikecamimo在同一个团队工作)。

当正确复制时,Windows窗体应用程序中也会出现此问题。在最初的操作中,这个问题没有出现在windows窗体中,因为没有阻塞。当使用ResetEvent引入阻塞时,也会出现同样的问题。

这是因为事件处理程序(Widget_Completed)与调用Widget.DoWork的方法位于同一线程中。AutoResetEvent.WaitOne();永远阻塞的结果,因为从未调用事件处理程序来设置事件。

在windows窗体环境中,可以通过使用Application.DoEvents轮询消息队列并允许处理事件来解决此问题。见下文。

代码语言:javascript
运行
复制
using System;
using System.Threading;
using System.Windows.Forms;

class Program
{
    EventArgs data;

    static void Main()
    {
        Program p = new Program();
        p.RunWidget();
    }

    public Program()
    {
        _autoEvent = new AutoResetEvent(false);
    }

    public void RunWidget()
    {
        ThirdParty widget = new ThirdParty();                   
        widget.Completed += new EventHandler(this.Widget_Completed);
        data = null;
        widget.DoWork();

        while (data == null);
            Application.DoEvents();

        // do stuff with the results of DoWork that are contained in EventArgs.
    }

    // Assumes that some kind of args are passed by the event
    public void Widget_Completed(object sender, EventArgs e)
    {
        data = e;
    }
}

在非windows窗体应用程序中,应用程序不可用,因此无法调用DoEvents。

问题出在线程化上,而widget.DoWork的关联事件处理程序需要在另一个线程上。这应该可以防止AutoResetEvent.WaitOne无限期地阻塞。我想..。:)

任何关于如何实现这一点的想法都将是非常棒的。

票数 1
EN

Stack Overflow用户

发布于 2012-10-01 22:11:37

代码语言:javascript
运行
复制
AutoResetEvent _autoEvent = new AutoResetEvent(false);

public  WebBrowser SyncronNavigation(string url)
{
    WebBrowser wb  = null;

    wb = new WebBrowser();
    wb.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(wb_DocumentCompleted);

    wb.ScriptErrorsSuppressed = true;
    wb.Navigate(new Uri(url));

    while (!_autoEvent.WaitOne(100))
        Application.DoEvents();

    return wb;
}

void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
    //throw new NotImplementedException();
    _autoEvent.Set();
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/475617

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档