Exp*_*ice 0 .net c# console-application
我有这个Windows控制台应用程序:
using System;
using System.Text;
namespace ThreadLockSample
{
class Program
{
static void P1(System.Data.DataTable dt)
{
for (int i = 0; i < 100000; i++)
{
dt.Rows.Add(i);
}
}
static void P2(System.Data.DataTable dt)
{
for (int i = 100000; i < 200000; i++)
{
dt.Rows.Add(i);
}
}
static void Main(string[] args)
{
System.Data.DataTable dt = new System.Data.DataTable();
for (int i = 0; i < 200; i++)
dt.Columns.Add("Id " + i);
System.Threading.Thread t1 = new System.Threading.Thread(() => P1(dt));
System.Threading.Thread t2 = new System.Threading.Thread(() => P2(dt));
t1.Start();
t2.Start();
t1.Join();
t2.Join();
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在我传递的DataTable可以访问两个线程,但应用程序冻结 - 如何更改我的代码以删除此问题.
运行此应用程序时,您不会遇到死锁.相反,您会收到一条错误,指出某些数据已损坏,DataTable因为它DataTable本身有一些内部的并发检查.
我想这个应用程序是你的真实应用程序的简单版本.您可以采取以下几个步骤来改进您的计划:
使用共享数据进行多线程处理很困难.您可以简化程序,以便不需要任何共享数据吗?也许你可以并行运行两个操作,返回一个结果,然后合并这些结果.这样可以避免许多潜在的问题.
如果不可能,您可以执行以下操作:
你创建一个像这样的锁对象:
private static object _lock = new object();
Run Code Online (Sandbox Code Playgroud)
现在,您可以使用以下命令对数据表进行调用:
lock (_lock)
{
dt.Rows.Add(i);
}
Run Code Online (Sandbox Code Playgroud)
一个Task目标是围绕一个主题的智能包装.建议使用任务.
Task t1 = Task.Run(() => P1(dt));
Task t2 = Task.Run(() => P2(dt));
Task.WaitAll(t1, t2);
Run Code Online (Sandbox Code Playgroud)
由于最初的问题现在已从死锁变为冻结,因此还需要考虑其他一些事项.
在控制台应用程序中,您将始终等待某个时间点,直到完成两个任务.等待将冻结您的UI.当然,你可以使用像Timer这样的聪明的东西来检查任务是否已完成,但是控制台应用程序确实不适用于这种情况.
但是,如果您的应用程序实际上是一个WinForms或WPF应用程序,您应该考虑使用异步代码和C#5中添加的新async/await关键字.它们与Tasks完美配合,它们允许您在另一个线程上运行代码,同时UI保持响应.任务完成后,结果将合并回UI线程,用户将保留响应式应用程序.
有关async/await的更多信息,您可以从这里开始:使用Async和Await进行异步编程(C#和Visual Basic)
| 归档时间: |
|
| 查看次数: |
538 次 |
| 最近记录: |