Task.run和threadpool.QueueUserWorkItem
Task.Run
和 ThreadPool.QueueUserWorkItem
都是在 .NET 中用于执行异步任务的方法,但它们之间有一些区别。
- 返回值类型不同:
Task.Run
返回一个Task
对象,而ThreadPool.QueueUserWorkItem
没有返回值。 - 参数不同:
Task.Run
接受一个Func<Task>
或Action
委托,而ThreadPool.QueueUserWorkItem
接受一个WaitCallback
委托。 - 线程池的使用方式不同:
Task.Run
会使用线程池中的线程来执行任务,而ThreadPool.QueueUserWorkItem
只能使用线程池中的线程来执行任务。 - 异常处理不同:
Task.Run
可以通过await
关键字或Task.Wait
方法等方式来捕获任务中的异常,而ThreadPool.QueueUserWorkItem
没有提供类似的机制,需要在任务中自行处理异常。
综上所述,Task.Run
更加灵活,可以更好地支持异步编程模式,而 ThreadPool.QueueUserWorkItem
更适合执行简单的后台任务。在一般情况下,建议使用 Task.Run
来执行异步任务。
在C#中,用于同步线程的机制有以下几种:
-
Monitor:用于同步在同一个进程内的线程。
-
Mutex:用于同步跨进程的线程。
-
Semaphore:用于控制同时访问某个资源的线程数量。
-
AutoResetEvent:用于线程之间的通信,允许一个线程在等待另一个线程信号时暂停执行。
-
ManualResetEvent:与AutoResetEvent类似,但允许多个线程同时等待信号。
-
CountdownEvent:允许一个线程等待多个线程完成。
-
Barrier:用于同步多个线程,允许线程在达到某个点时暂停执行。
-
ReaderWriterLock:允许多个线程同时读取某个资源,但只允许一个线程写入。
-
SpinLock:用于在高并发情况下保护共享资源。
以上这些同步机制都有其特定的使用场景和优缺点,需要根据具体的需求来选择适合的同步机制。
Invoke与BeginInvoke的不同
不同点: Invoke是同步更新,会阻塞所在工作者线程,BeginInvoke是异步更新,不会阻塞当前线程。 Invoke调用后将指定代码立即插入主线程中执行,而BeginInvoke调用后,发送消息给UI线程, 相当于向Dispatcher队列中添加工作项,待之前UI更新任务完成后,再执行BeginInvoke中的内容。 在使用场景上,Invoke方法会拖延线程直到执行完指定代码,如果需要暂停异步操作,直到用户提供反馈信息,可使用Invoke, 比如指定代码弹出YES/NO对话框,需要根据用户反馈以进一步执行操作的场景。 相同点:两者虽然一个为同步,一个为异步,实际是运行在同一线程,即UI主线程。
常用的委托类型
- Action:表示一个不返回值、不带参数的委托。
- Func:表示一个带有一个返回值、不带参数的委托。
- Predicate:表示一个带有一个返回值、一个参数的委托。
- EventHandler:表示一个用于处理事件的委托,它带有两个参数,第一个参数是事件源对象,第二个参数是事件参数。
- EventHandler
:表示一个用于处理事件的委托,它带有两个参数,第一个参数是事件源对象,第二个参数是事件参数,其中事件参数类型为 TEventArgs。 - Action
:表示一个不返回值、带有一个参数的委托,参数类型为 T。 - Action<T1, T2>:表示一个不返回值、带有两个参数的委托,参数类型分别为 T1 和 T2。
- Action<T1, T2, T3>:表示一个不返回值、带有三个参数的委托,参数类型分别为 T1、T2 和 T3。
- Func
:表示一个带有一个返回值、不带参数的委托,返回值类型为 T。 - Func<T, TResult>:表示一个带有一个参数、一个返回值的委托,参数类型为 T,返回值类型为 TResult。
- Func<T1, T2, TResult>:表示一个带有两个参数、一个返回值的委托,参数类型分别为 T1 和 T2,返回值类型为 TResult。
- Func<T1, T2, T3, TResult>:表示一个带有三个参数、一个返回值的委托,参数类型分别为 T1、T2 和 T3,返回值类型为 TResult。
这些委托类型都是 .NET Framework 中预定义的常用委托类型,你也可以自定义委托类型来满足特定的需求。