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

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(使用前将#替换为@)

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

  • 线程安全的异步字节队列

    我有一个回调方法 只要有新数据可用 就会调用该方法 public delegate void DataCallback byte buffer int offset int count 我想将其包装在一个实现与此类似的接口的类中 publi
  • SLURM 节点、任务、核心和 CPU

    有人能够澄清这些东西到底是什么吗 据我所知 节点是集群内的计算点 本质上是一台计算机 任务是可以在单个节点或多个节点上执行的进程 核心基本上是指您希望在单个节点上分配多少 CPU 来执行分配给该 CPU 的任务 它是否正确 我混淆了什么吗
  • WinForms - 表单大小错误

    我们有以下代码 private void MainForm Shown object sender EventArgs e RepositionForm private void RepositionForm Rectangle rect
  • 带等待/通知的同步块与不带等待/通知的同步块之间的区别?

    如果我只是使用synchronized 不是wait notify方法 它仍然是线程安全的吗 有什么不同 Using synchronized使方法 块一次只能由一个线程访问 所以 是的 它是线程安全的 这两个概念是结合在一起的 而不是相互
  • 如何在 Winform DataGridView 中创建不同的单元格格式

    我有一个 DataGridView 我将其绑定到 DataTable DataTable 是一个全数字值 要求 DataGridView 中的每 n 行都包含文本 而不是数值 以便在视觉上为用户分隔部分 我很高兴在绑定后将此文本数据放入 D
  • 如何从 Android 调用 RESTful 方法?

    我尝试了两种不同的方法来从 Android 调用简单的 REST 方法 所述 REST 方法 适用于其他客户端 仅返回一个 int val 例如 17 以下两次尝试都是基于我在网上找到的代码 有一种是这样的 公共无效onFetchBtnCl
  • WinForms 中的 EF:如何过滤 BindingSource/DGW 中的数据 (.Local.ToBindingList())

    我按照本教程生成了 EF 模型 首先是数据库 和数据源http msdn microsoft com en us data jj682076 aspx http msdn microsoft com en us data jj682076
  • 设置 Form.KeyPreview = true 的缺点?

    我想知道 Form KeyPreview 属性实际上有什么用处 它为什么存在以及将其设置为 true 会带来什么 风险 我想它一定有some负面影响 否则它根本不应该存在 或者至少默认情况下是正确的 EDIT 我很清楚what确实如此 我问
  • 如何获取 TextRenderer 使用的确切文本边距

    System Windows Forms TextRenderer DrawText方法根据 的值呈现带或不带左右填充的格式化文本flags范围 TextFormatFlags NoPadding 将文本紧密地装入边界框 TextForma
  • 使用 gcc 在 Linux 上运行线程构建块 (Intel TBB)

    我正在尝试为线程构建块构建一些测试 不幸的是 我无法配置 tbb 库 链接器找不到库 tbb 我尝试在 bin 目录中运行脚本 但这没有帮助 我什至尝试将库文件移动到 usr local lib 但这又失败了 任何的意见都将会有帮助 确定您
  • 随机数但不重复

    我想生成一个小于 50 的随机数 但一旦生成该数字 我希望它不能再次生成 谢谢您的帮助 请参见 费舍尔 耶茨洗牌 http en wikipedia org wiki Fisher E2 80 93Yates shuffle public
  • Hazelcast 分布式锁与 iMap

    我们目前使用 Hazelcast 3 1 5 我有一个简单的分布式锁定机制 应该可以跨多个 JVM 节点提供线程安全性 代码非常简单 private static HazelcastInstance hInst getHazelcastIn
  • 使用来自多个 kafka 主题的消息的最佳实践是什么?

    我需要消费来自不同卡夫卡主题的消息 我是否应该为每个主题创建不同的消费者实例 然后根据分区数量启动一个新的处理线程 或者 我应该从单个消费者实例订阅所有主题 并且应该启动不同的处理线程 感谢和问候 梅加 唯一的规则是 您必须考虑 Kafka
  • 使用 Thread.Sleep 等待的替代方法

    首先我不是在问同样的问题C Thread Sleep 的替代方案 https stackoverflow com questions 5450353 c sharp alternative to thread sleep or C 中 Th
  • 如何以编程方式对 WebBrowser 控件安全警报回答“是”

    我正在使用 WebBrowser 控件以编程方式访问单个网站 但每当我登录时 我都会收到此证书安全警报 由于我信任该网站 并且我还需要以编程方式自动登录 因此此对话框会妨碍我 我搜索了解决方案并发现一个和我类似的问题 https stack
  • Final字段的线程安全

    假设我有一个 JavaBeanUser这是从另一个线程更新的 如下所示 public class A private final User user public A User user this user user public void
  • 如何在vb.net中对datagridview的3列进行排序

    下面我想对 ProductCode ColorCode 和 Size 列进行排序 请指导 对 大小 列中的信息进行排序 Size Number sequence XS 1 S 2 M 3 L 4 XL 5 XXL 6 2L 7 3L 8 4
  • 什么时候值得使用 BindingSource?

    我想我非常了解 BindingSource 类的作用 即在数据源和 UI 控件之间提供一个间接层 它实现了 IBindingList 接口 因此还提供了对排序的支持 而且我已经经常使用它 没有太多问题 但我想知道我使用它的频率是否超过了应有
  • 从Web API同步调用外部api

    我需要从我的 Web API 2 控制器调用外部 api 类似于此处的要求 使用 HttpClient 从 Web API 操作调用外部 HTTP 服务 https stackoverflow com questions 13222998
  • 在 String.Format 中插入格式化字符?

    我用谷歌搜索了这个 但 VB Net 2008 似乎不允许在 String Format 中插入格式化字符 例如 t r n BAD MessageBox Show String Format 0 tab 1 Foo Bar BAD Mes

随机推荐

  • 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