我有一个应用程序需要在应用程序启动时读取非常大的.CSV
文件,并将每行转换为object
。这些是读取文件的方法:
public List<Aobject> GetAobject()
{
List<Aobject> Aobjects = new List<Aobject>();
using (StreamReader sr = new StreamReader(pathA, Encoding.GetEncoding("Windows-1255")))
{
string line;
while ((line = sr.ReadLine()) != null)
{
string[] spl = line.Split(',');
Aobject p = new Aobject { Aprop = spl[0].Trim(), Bprop = spl[1].Trim(), Cprop = spl[2].Trim() };
Aobjects.Add(p);
}
}
return Aobjects;
}
public List<Bobject> GetBobject()
{
List<Bobject> Bobjects = new List<Bobject>();
using (StreamReader sr =
new StreamReader(pathB, Encoding.GetEncoding("Windows-1255")))
{
//parts.Clear();
string line;
while ((line = sr.ReadLine()) != null)
{
string[] spl = line.Split(',');
Bobject p = new Bobject();
p.Cat = spl[0];
p.Name = spl[1];
p.Serial1 = spl[3].ToUpper().Contains("1");
if (spl[4].StartsWith("1"))
p.Technical = 1;
else if (spl[4].StartsWith("2"))
p.Technical = 2;
else
p.Technical = 0;
Bobjects.Add(p);
}
}
return Bobjects;
}
这会阻止我的UI
几秒钟,所以我试图让它成为multi-Threaded
。但是我的所有测试都表明un-threaded
场景更快。这是我测试它的方式:
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < 1000; i++)
{
Dal dal = new Dal();
Thread a = new Thread(() => { ThreadedAobjects = dal.GetAobject(); });
Thread b = new Thread(() => { ThreadedBobjects = dal.GetBobject(); });
a.Start();
b.Start();
b.Join();
a.Join();
}
sw.Stop();
txtThreaded.Text = sw.Elapsed.ToString();
Stopwatch sw2 = new Stopwatch();
sw2.Start();
for (int i = 0; i < 1000; i++)
{
Dal dal2 = new Dal();
NonThreadedAobjects = dal2.GetAobject();
NonThreadedBobjects = dal2.GetBobject();
}
sw2.Stop();
txtUnThreaded.Text = sw2.Elapsed.ToString();
结果:
线程运行:00:01:55.1378686
UnTreaded run:00:01:37.1197840
已编译为.Net4.0
,但也应在.Net3.5
下以发布模式运行
有些人可以解释为什么会发生这种情况,我该如何改进呢?
答案 0 :(得分:5)
您忽略了与创建和启动线程相关的成本。而不是创建新线程尝试使用线程池:
ThreadPool.QueueUserWorkItem(() => { ThreadedAobjects = dal.GetAobject(); });
为了正确计算总时间,您还需要计算已完成的操作次数。请看一下这个链接:http://msdn.microsoft.com/en-us/library/3dasc8as.aspx
答案 1 :(得分:1)
我建议使用一个调用GetAobject
然后调用GetBobject
的线程。您的任务几乎肯定是I / O绑定的,如果这两个文件非常大并且在同一个驱动器上,那么尝试同时访问它们将导致大量不必要的磁盘搜索。所以你的代码变成了:
ThreadPool.QueueUserWorkItem(() =>
{
AObjects = GetAObject();
BObjects = GetBObject();
});
这也简化了您的代码,因为您只需要在一个ManualResetEvent
上进行同步。
答案 2 :(得分:0)
如果您将运行此测试,每次都会得到稍微不同的结果。运行时计算机上发生的许多事情导致事情发生的时间 - 例如:其他进程,GC等。
但你的重新开始是合理的,因为拥有另一个线程意味着进程需要更多的上下文切换,并且每个上下文都需要时间......
你可以在上下文开关上阅读更多内容: http://en.wikipedia.org/wiki/Context_switch
答案 3 :(得分:0)
添加到Slugart的正确答案:您的并行化在许多方面都是无效的,因为您等待第一个线程完成,而第二个线程可以更快地完成并且在一段时间内不执行任务(查看任务并行库和PLINQ)
此外,您的操作是IO绑定的,这意味着并行性取决于IO设备(某些设备更好地以顺序方式执行,并且尝试执行多次读取将减慢整体操作)。