如何使用定时器和不同的线程让代码顺利运行

2024-04-15

我试图阻止 GUIfreezing,因为定时器间隔很短并且需要处理的内容太多Timer.Tick事件处理程序。
我已经用谷歌搜索了一段时间,我了解到我无法从 UI 线程以外的任何其他线程更新 UI。

那么,如果您在下面使用大量控件怎么办?Timer1.Tick?
当使用带有计时器的 WebClient 下载数据时,如何更新标签,您不想将间隔降低太多并同时保持 UI 响应?

当我访问 UI 元素、ListBox1 和 RichTextBox 时,我收到跨线程违规异常。

使用计时器和/或线程更新 UI 而不会导致交叉威胁异常的正确方法是什么?


您可以使用不同的方法从 UI 线程以外的线程更新 UI 元素。
您可以使用InvokeRequired/Invoke()图案 (meh),调用异步 BeginInvoke()方法,Post() https://learn.microsoft.com/en-us/dotnet/api/system.threading.synchronizationcontext.post to the 同步上下文 https://learn.microsoft.com/en-us/dotnet/api/system.threading.synchronizationcontext,也许与一个混合异步操作 https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.asyncoperation + 异步操作管理器 https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.asyncoperationmanager(纯 BackGroundWorker 风格),使用异步回调等。

还有Progress<T> https://learn.microsoft.com/en-us/dotnet/api/system.progress-1类及其IProgress<T> https://learn.microsoft.com/en-us/dotnet/api/system.iprogress-1界面。
这个类提供了一种非常简单的方法来捕获SynchronizationContext创建类对象的位置以及Post()返回到捕获的执行上下文。
The Progress<T>在 UI 线程中创建的委托在该上下文中被调用。我们只需要通过Progress<T>委托并处理我们收到的通知。
您正在下载并处理一个字符串,因此您的Progress<T>对象将是Progress(Of String):所以,它会返回一个字符串给你。

计时器被替换为任务,该任务执行您的代码,并按您可以指定的时间间隔延迟其操作,与计时器一样,此处使用任务.延迟([间隔]) https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.delay每个之间action。有一个跑表 https://learn.microsoft.com/en-us/dotnet/api/system.diagnostics.stopwatch测量下载实际花费的时间和adjusts基于指定间隔的延迟(它不是精密的东西, 反正)。


▶ 在示例代码中,可以使用以下命令启动和停止下载任务StartDownload() and StopDownload()辅助类的方法。
The StopDownload()方法是可等待的,它执行当前任务的取消并处理使用的一次性对象。

▶ 我已经用HttpClient替换了WebClient,它使用起来仍然很简单,它提供了支持异步方法CancellationToken(尽管正在进行的下载需要某个时间取消,但在这里处理)。

▶ 单击按钮可初始化并开始定时下载,单击按钮可停止下载(但您可以调用StopDownload()表单关闭时的方法,或者,好吧,每当您需要时)。

▶ The Progress<T>delegate 这里只是一个 Lambda:没什么可做的,只需填充一个 ListBox 并滚动一个 RichTextBox 即可。
您可以初始化辅助类对象(它的名称是MyDownloader:当然你会选择另一个名字,这个名字很荒谬)并称之为StartDownload()方法,通过Progress<T>对象,即UriInterval每次下载之间。

Private downloader As MyDownloader = Nothing

Private Sub btnStartDownload_Click(sender As Object, e As EventArgs) Handles btnStartDownload.Click
    Dim progress = New Progress(Of String)(
        Sub(data)
            ' We're on the UI Thread here
            ListBox1.Items.Clear()
            ListBox1.Items.AddRange(Split(data, vbLf))
            RichTextBox1.SelectionStart = RichTextBox1.TextLength
        End Sub)

    Dim url As Uri = New Uri("https://SomeAddress.com")
    downloader = New MyDownloader()
    ' Download from url every 1 second and report back to the progress delegate
    downloader.StartDownload(progress, url, 1)

Private Async Sub btnStopDownload_Click(sender As Object, e As EventArgs) Handles btnStopDownload.Click
    Await downloader.StopDownload()
End Sub

辅助类:

Imports System.Diagnostics
Imports System.Net
Imports System.Net.Http
Imports System.Text.RegularExpressions

Public Class MyDownloader
    Implements IDisposable

    Private Shared client As New HttpClient()
    Private cts As CancellationTokenSource = Nothing
    Private interval As Integer = 0
    Private disposed As Boolean

    Public Sub StartDownload(progress As IProgress(Of String), url As Uri, intervalSeconds As Integer)
        
        interval = intervalSeconds * 1000
        Task.Run(Function() DownloadAsync(progress, url, cts.Token))
    End Sub

    Private Async Function DownloadAsync(progress As IProgress(Of String), url As Uri, token As CancellationToken) As Task
        token.ThrowIfCancellationRequested()

        Dim responseData As String = String.Empty
        Dim pattern As String = "<(?:[^>=]|='[^']*'|=""[^""]*""|=[^'""][^\s>]*)*>"
        Dim downloadTimeWatch As Stopwatch = New Stopwatch()
        downloadTimeWatch.Start()
        Do
            Try
                Using response = Await client.GetAsync(url, HttpCompletionOption.ResponseContentRead, token)
                    responseData = Await response.Content.ReadAsStringAsync()
                    responseData = WebUtility.HtmlDecode(Regex.Replace(responseData, pattern, ""))
                End Using
                progress.Report(responseData)

                Dim delay = interval - CInt(downloadTimeWatch.ElapsedMilliseconds)
                Await Task.Delay(If(delay <= 0, 10, delay), token)
                downloadTimeWatch.Restart()
            Catch tcEx As TaskCanceledException
                ' Don't care - catch a cancellation request
                Debug.Print(tcEx.Message)
            Catch wEx As WebException
                ' Internet connection failed? Internal server error? See what to do
                Debug.Print(wEx.Message)
            End Try
        Loop
    End Function

    Public Async Function StopDownload() As Task
        Try
            cts.Cancel()
            client?.CancelPendingRequests()
            Await Task.Delay(interval)
        Finally
            client?.Dispose()
            cts?.Dispose()
        End Try
    End Function

    Protected Overridable Sub Dispose(disposing As Boolean)
        If Not disposed AndAlso disposing Then
            client?.Dispose()
            client = Nothing
        End If
        disposed = True
    End Sub

    Public Sub Dispose() Implements IDisposable.Dispose
        Dispose(True)
    End Sub
End Class
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用定时器和不同的线程让代码顺利运行 的相关文章

  • 为什么Apache MPM prefork.c 使用互斥体来保护accept()?

    我坐下来读书Apache 的 MPM prefork c http code metager de source xref apache httpd server mpm prefork prefork c这段代码使用了一个名为accept
  • 创建具有特定权限的线程C++

    我有一个多线程应用程序 我想创建一个具有不同用户权限的线程 例如 多域管理员权限 但我找不到任何 Win32 APICreateThread要做到这一点 如何创建具有特定用户权限的线程 thanks 调用 CreateThread CREA
  • 理解 JavaScript 的单线程本质

    我一直在阅读 John Resig 的 JavaScript Ninja 的秘密 它解释了 JavaScript 是单线程的 但是 我尝试对此进行测试 但我不确定要从这里删除什么 executing this in browser func
  • std::condition_variable::wait_for 和 std::condition_variable::wait_until 有什么区别?

    The 我正在使用的参考 http en cppreference com w cpp thread condition variable对两者的解释如下 wait for 阻塞当前线程 直到条件变量被唤醒或在指定的超时持续时间之后 wai
  • 将字符串转换为双精度 - VB

    VB中有没有一种有效的方法来检查字符串是否可以转换为双精度型 我目前正在尝试将字符串转换为双精度型 然后查看它是否引发异常 但这似乎减慢了我的申请速度 Try if number then format it current CDbl x
  • 通过推送通知唤醒

    Suppose 有一些对象 例如 一个数组a 和依赖于对象的条件 例如 a empty 当前线程以外的某些线程可以操作该对象 a 因此条件评估值的真实性会随着时间的推移而变化 如何让当前线程在代码中的某个时刻休眠 并在条件满足时通过推送通知
  • 如何限制Erlang VM(BEAM)使用的核心数量?

    我正在具有 2 个四核 Xeon E5520 2 2GHz 24 0GB RAM 和 Erlang R15B02 启用 SMP 的节点上运行实验 我想知道是否可以限制Erlang VM使用的核心数量 以便我可以暂时禁用一些核心并逐步增加数量
  • 平滑滚动.net 表单

    您好 我正在 net 中使用表单 并且在运行时动态添加大量链接标签 我将这些链接标签添加到面板并将该面板添加到 winform 当链接标签的数量增加时 表单会显示一个自动滚动条 垂直 现在 当我使用自动滚动向下滚动时 表单在滚动时不会更新其
  • 新任务中使用的依赖注入服务

    我在需要时使用依赖项注入来访问我的服务 但我现在想要创建一个并发任务 但这会由于依赖项注入对象及其生命周期而导致问题 我读过这篇文章 标题 防止多线程 Link http mehdi me ambient dbcontext in ef6
  • 以异步方式执行 Express res.render

    我有一个 Nodejs 应用程序 其中res renderExpress 方法以阻塞方式花费大约 400 毫秒 我如何处理它以非阻塞方式执行 我的 apache 基准测试需要 12 秒来执行大约 30 个并发请求 我如何以更好的方式实施这一
  • 在 Python 中打印守护线程异常

    Python 不会打印守护线程中引发的异常的回溯消息 例如 以下代码创建一个守护线程并在新线程中引发异常 def error raiser raise Exception import threading thread threading
  • 如何停止提交给 ExecutorService 的 Callable?

    我正在尝试实现一个示例应用程序来测试Callable and ExecutorService接口 在我的应用程序中我已经声明 ExecutorService exSvc Executors newSingleThreadExecutor T
  • 如何四舍五入到一半,始终为正方向? [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 如何实现以下舍入 0 0126083
  • 从 Handler.obtainMessage() 获取什么参数

    我正在使用线程来执行一些 BT 任务 我正在尝试向 UI 线程发送消息 以便我可以基于我的 BT 线程执行 UI 工作 为此 我使用处理程序 但我不知道如何检索发送到处理程序的数据 要发送数据 我使用 handler obtainMessa
  • 从另一个 FORM 中取回隐藏的 FORM

    我有两种形式Form1 and Form2 我正在打开Form2 from Form1 on button Click Form2 obj2 new Form2 this Visible false obj2 Show 然后我想回来Form
  • 如何调整 Windows 窗体以适应任何屏幕分辨率?

    我知道这是重复的问题 但我检查了所有其他相关问题 他们的答案没有帮助 结果仍然与屏幕截图 2 中所示相同 我是 C Windows 窗体新手 如截图1所示 我有Form1有一些控件 每组控件都放在一个面板中 我在 PC1 中设计了应用程序
  • 使用单独的线程在java中读取和写入文件

    我创建了两个线程并修改了 run 函数 以便一个线程读取一行 另一个线程将同一行写入新文件 这种情况会发生直到整个文件被复制为止 我遇到的问题是 即使我使用变量来控制线程一一执行 但线程的执行仍然不均匀 即一个线程执行多次 然后控制权转移
  • 当底层连接是有状态时如何使用 Apache HttpClient?

    我在谷歌上搜索了很多关于如何使用 HttpClient 进行多线程处理的信息 他们中的大多数人建议使用 ThreadSafeClientConnManager 但我的应用程序必须登录某个主机 登录表单页面 以便 HttpClient 获得底
  • 对多个对象使用事件处理程序

    我有 20 件物品List
  • 如何使用 VB.NET 打开受密码保护的共享网络文件夹?

    我需要在网络上打开受密码保护的共享文件夹才能访问 Access 97 数据库 如何打开文件夹并输入密码 在这里找到http www mredkj com vbnet vbnetmapdrive html http www mredkj co

随机推荐

  • Java 中受保护的访问修饰符

    我在理解java中的受保护访问修饰符 或其背后的设计 时遇到了一些困难 我认为这意味着包访问和通过继承包含抽象成员的类的对象进行访问 我编写了以下示例代码 我发现如果未注释 注释掉的行会产生编译错误 为什么我可以通过 Second 中的 S
  • 是否可以在应用程序组件上使用 [ngClass],其中该类位于 Angular 6 的组件内部?

    我有一个 Angular 6 应用程序 我正在尝试将另一个 CSS 类应用到我的应用程序组件之一app component html文件 基本上 我想根据条件更改应用程序页脚的颜色 而所有其他情况都不显示页脚 所以 我的代码如下所示 应用程
  • 我的 Visual Studio 项目是 Web 应用程序还是网站?

    首先 什么时候使用什么以及它们之间的总体差异之前已经回答过 但我找不到这个问题的答案 在哪里可以检查我的 Visual Studio 项目是 Web 应用程序还是网站 区分网站和 Web 应用程序的最简单方法是查看项目的图标 Web Sit
  • C# IComparer 标准用法问题

    我有一个问题 这是否是在 C 中使用 IComparer 的标准 假设我有一个情况 其中有三个 Person 对象 P1 P2 和 P3 假设我调用 Compare 方法并传入 P1 和 P2 结果为 0 这本质上意味着两个人应该被归类为相
  • Rails 6 ActiveStorage 在文件上传失败时恢复事务

    我有一个非常简单的场景 我正在创建一条记录 然后附加一个文件 之后save 因为我需要记录上的 id 来生成附件的细名 所有这些都包含在事务中 就像是 def create ActiveRecord Base transaction do
  • 在服务器中实现自动完成的最佳方法是什么?

    这个问题很容易让人知道 让 Web 应用程序的客户端自动完成变得漂亮很简单 有很多插件 但是 在后端 在服务器端 最好的方法是什么 我不喜欢用户每次按下按键就访问数据库的想法 我一直在考虑 sphinx 或者一些与您的网站并行运行的全文搜索
  • 如何使用 Java2D 图形正确绘制点间距很近的粗线?

    我正在尝试使用 Java2D 绘制地图 当我的地图缩小时 我的道路上充满了绘画制品 这是绘制完整的美国州时屏幕的一小部分 放大后 这是一段相似的路段 使用的线条样式是一条蓝色实线 其宽度缩放为相当于 2 个像素 我尝试了各种渲染提示和行连接
  • 在 TeamCity 中创建变更日志工件

    是否有一种简单的方法可以让 TeamCity 包含文本或 html 更改日志作为其输出工件之一 也许我需要沿着让 msbuild 或其他进程创建更改日志的路线 但由于 TeamCity 为每个构建生成一个更改日志 我想知道是否已经有一种简单
  • Bootstrap-modal 在 Flash 顶部弹出

    我正在使用 Twitter 的 Bootstrap 插件bootstrap modal 除非后面有闪光灯元件 否则它效果很好 当引导模式对话框出现并且其后面有一个 Flash 元素时 Flash 元素位于其他所有元素之上 我该如何解决 您需
  • Ruby String#scan 相当于返回 MatchData

    正如问题标题中基本上所述 Ruby 字符串上是否有一种方法相当于字符串 扫描 http ruby doc org core String html method i scan但它不是只返回每个匹配的列表 而是返回一个数组MatchData是
  • 如何处理 SQL Server 中列名中的空格?

    假设我想使用这样的代码 select Response Status Code Client Response Status Code from TC Sessions NOLOCK WHERE StartDate BETWEEN 05 1
  • Oracle 数字和 varchar 连接

    我有一个连接两个表的查询 一个表的列类型为 varchar 另一表的列类型为 number 我已经在 3 个 Oracle 数据库上执行了查询 并且看到了一些奇怪的结果 希望能够得到解释 在其中两个数据库上 类似以下内容的工作 select
  • Dart future 阻塞主线程

    我正在开发一个捕获和处理图像的应用程序 代码的简化版本是 build return FloatingActionButton onPressed processImage child Icon Icons camera alt color
  • 计算numpy中2个点列表的距离

    我有 2 个点列表作为 numpy ndarray 每一行都是一个点的坐标 例如 a np array 1 0 0 0 1 0 0 0 1 b np array 1 1 0 0 1 1 1 0 1 这里我想计算2个列表中所有点对之间的欧氏距
  • Windows Server 2012 R2 上通过 SSL 的 AD LDS

    我正在尝试将我的 AD LDS 实例配置为通过 SSL 运行 以便我可以使用我的应用程序从另一台计算机连接到它并执行密码更改操作 我安装了证书颁发机构来创建一个服务器证书 我可以在我的 AD LDS 实例上使用该证书 我将证书添加到 AD
  • Quill:如何防止工具栏滚动并设置高度?

    我正在尝试遵循以下示例https quilljs com playground autogrow height https quilljs com playground autogrow height但在设置编辑器框的高度并防止工具栏滚动到
  • 在 Ubuntu 9.10 中安装 play-framework

    我已从 playframework org 网站复制了压缩文件并将其解压缩到某个位置 我已将其插入到我的 bashrc 配置文件中以设置为 PATH 环境 但仍然无法从任何地方访问播放命令 即使在框架的安装目录中 播放文件也没有按原样运行
  • 将 Selenium WebDriver 连接到现有浏览器会话

    我正在使用 selenium 如果当前存在现有浏览器会话 对于我来说 Chrome 我想附加一个 webdriver 实例 我不想打开新的浏览器窗口 会话 我用谷歌搜索发现 有一些方法可以通过这些网站上的描述来做到这一点 通过扩展 Remo
  • file.canWrite() 说“true”,但我无法在可移动存储上写入(kit kat)

    我收到来自相机的意图 其中包含在此路径中拍摄的照片 storage extSdCard DCIM Camera photoCaptured jpg 我想调整图像的大小 已经这样做了 并在同一路径中覆盖 我可以在 2 3 4 1 和 4 3
  • 如何使用定时器和不同的线程让代码顺利运行

    我试图阻止 GUIfreezing 因为定时器间隔很短并且需要处理的内容太多Timer Tick事件处理程序 我已经用谷歌搜索了一段时间 我了解到我无法从 UI 线程以外的任何其他线程更新 UI 那么 如果您在下面使用大量控件怎么办 Tim