【问题标题】:Threading or Task线程或任务
【发布时间】:2015-08-06 19:00:20
【问题描述】:

我目前正在重新学习 C# 并开发一个简单的应用程序,该应用程序发送广播消息并在收到时显示在 Windows 窗体上。

我有一个包含两个线程的发现类,一个每 30 秒广播一次,另一个线程在套接字上侦听。由于阻塞调用,它在一个线程中:

                if (listenSocket.Poll(-1, SelectMode.SelectRead))

第一个线程的工作原理很像类库中的计时器,它广播数据包,然后休眠 30 秒。

现在原则上它工作正常,当收到一个数据包时,我将它扔到一个事件中,Winform 将它放在一个列表中。问题始于表单,因为主 UI 线程需要 Invoke。现在我只有两个线程,从长远来看,当线程数量增加时,它似乎不是最有效的。

我已经探索了任务,但这些似乎更倾向于一次性长时间运行的任务(很像表单的后台工作人员)。

我发现的大多数线程示例都向控制台报告,并且没有调用和锁定变量的问题。

当我使用 .NET 4.5 时,我应该转到任务还是坚持线程?

【问题讨论】:

  • 您能否再描述一下您的情况 - 我不确定我是否了解您的主要担忧。

标签: c# multithreading


【解决方案1】:

如果您尝试从这样的线程更新 GUI,异步编程仍会将应用程序的某些方面委托给不同的线程(线程池),您将遇到与现在使用常规线程类似的问题。

但是,异步等待中有许多技术可以让您委托给后台线程,但会设置一个等待点,说当您完成该操作后请在 GUI 线程上继续,这可以有效地让您更新没有调用的 GUI 线程,并具有响应式 GUI。我说的是configureAwait。但也有其他技术。

如果您还不了解异步等待机制,这将花费您一些时间来学习所有这些新事物。但你会发现它非常有益。 但是,您是否愿意花几天时间学习和试验对您来说是新的技术,这取决于您自己。

Google 有点关于异步等待,有一些来自 Stephen Cleary 的优秀文章,例如 http://blog.stephencleary.com/2012/02/async-and-await.html

【讨论】:

  • 我确实读过这篇文章,这将解决 Invoke,但我将如何进入我现在用作广播的“无限”循环。以后我不会总是有 Winforms 应用程序,但很可能会写入数据库,然后在网页中查看。否则,我将在我的类上拥有一个 publick 属性,它将公开 List 并在 Get 祖先中有一个锁定机制以使其线程安全。
  • Webrequests、数据库访问等,你会发现api有异步方法可以使用。这意味着重新设计你今天拥有的东西。这不是在公园里散步。
  • 这是我的困惑,我的线程会抛出一个事件,到这里就可以了。我将与 EF 和异步一起使用的数据库。我只是不确定Task如何替换我的无限循环线程,它本质上是一个计时器。在某一时刻,我必须定期调用广播例程。具有线程的类上的每个属性都应该使用锁来保护它们吗?
  • 异步和等待的整个概念是关于并发而不是多线程。多线程是并发的一种形式。使用 async and wait 时,即使它们存在,您也看不到线程,并且您不能使用锁。但也许你应该在第一次尝试时发布更具体的问题。人们可以在这里提供帮助。
【解决方案2】:

首先,如果您担心可扩展性,您可能应该从易于扩展的方法开始。 ThreadPool 会很好用。任务也基于ThreadPool,它们允许更复杂的情况,例如按顺序触发的任务/线程(也基于条件)、同步等。在您的情况下(服务器和客户端),这似乎是不必要的。

其次,在我看来,您担心会出现瓶颈场景,即多个线程会尝试访问 UI 或 DB 等公共资源。使用 DB - 不要担心它们可以很好地处理多个访问。但是对于 UI 或其他非多线程友好的资源,您必须自己管理并行访问。我会建议像BlockingCollection 这样的东西,这是实现“许多生产者,一个消费者”模式的好方法。这样,您可以让多个线程添加内容,而只有一个线程从集合中读取内容并将其传递给 UI 等单线程资源。

顺便说一句,任务也可以长时间运行,即运行循环。检查this 文档。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 2014-05-06
    • 1970-01-01
    • 2015-03-27
    相关资源
    最近更新 更多