代码之家  ›  专栏  ›  技术社区  ›  CruleD

创建对象时未启动Webclient下载

  •  0
  • CruleD  · 技术社区  · 6 年前

    它在主线程上运行良好。


    就像这样,它不起作用:

    Dim AddRPB As New ProgressBar
    Dim client As New WebClient
    AddHandler client.DownloadProgressChanged, AddressOf DownloadingProgress
    AddHandler client.DownloadDataCompleted, AddressOf DownloadComplete
    client.DownloadDataAsync(New Uri(WebLink), Data)
    

    就像这样,它工作:

    Dim client As New WebClient
    AddHandler client.DownloadProgressChanged, AddressOf DownloadingProgress
    AddHandler client.DownloadDataCompleted, AddressOf DownloadComplete
    client.DownloadDataAsync(New Uri(WebLink), Data)
    Dim AddRPB As New ProgressBar
    

    Dim AddRPB As New ProgressBar
    

    1 回复  |  直到 6 年前
        1
  •  1
  •   Community CDub    5 年前

    这可能不完全准确,但以下是我通过一些测试和来自 Reference Source :

    没有/在实例化 ProgressBar

    WebClient 配合 SynchronizationContexts 为了将数据发布回UI线程并调用其事件处理程序(如 BackgroundWorker Async 方法 立即创建绑定到的异步操作 SynchronizationContext 调用线程的。如果上下文不存在,将创建一个新的上下文并将其绑定到该线程。

    RunWorkerAsync 没有(或之前)创建 进度条 幕后工作者 这是我的线。

    创建 进度条 之前

    进度条 在开始下载之前,实例化代码已经就位。现在,您正在非UI线程中创建一个控件,这将导致一个新的 行绪 行绪 有点不同,因为它是一个 WindowsFormsSynchronizationContext Control.Invoke() Control.BeginInvoke()

    这似乎是出问题的地方。通过在非UI线程中创建控件,从而创建 WindowsFormsSynchronizationContext 在该线程中 现在将在调用事件处理程序时使用该上下文。这个 将呼叫 WindowsFormsSynchronizationContext.Post() Control.BeginInvoke() 在同步上下文的线程上执行该调用。唯一的问题是:该线程没有处理 BeginInvoke 消息

    • 无消息循环= 异步调用

    • 未调用该方法= DownloadProgressChanged DownloadDataCompleted

    最后,这一切再一次归结为WinForms的黄金法则:

    将所有与UI相关的工作留在UI线程上!


    编辑:

    对于异步方法,您可以这样解决它,并让 在UI线程上创建,然后为您返回:

    Dim AddRPB As ProgressBar = Me.Invoke(Function() New ProgressBar)
    
    AddHandler client.DownloadProgressChanged, AddressOf DownloadingProgress
    AddHandler client.DownloadDataCompleted, AddressOf DownloadComplete
    
    client.DownloadDataAsync(New Uri(WebLink), AddRPB)