确定,
这是这些“概念性问题”中的一个,但我希望我能在正确的方向上找到一些指示。首先是期望的场景:
使用Tamir.SharpSsh提供的SFTP类,这两件事情都非常简单,但如果我只使用一个线程,那就有点慢了。特别是对子目录的递归会得到非常“UI阻塞”,因为我们讨论的是10.000个目录。
我的基本方法很简单,创建某种“池”,我保持10个开放的SFTP连接。然后查询第一个工作人员以获取目录列表。如果获得此列表,则发送下一个免费工作人员(例如1-10,第一个也可以再次免费)以获取子目录详细信息。一旦有工人自由,就把他送到子包装。等等...
我知道ThreadPool,简单的线程并做了一些测试。令我困惑的是以下内容:我基本上需要......
我目前不确定实施细节,尤其是“要做的工作”和“维护线程列表”部分。
这是一个好主意:
好的,到目前为止......
不过,我还可以使用PRISM事件和命令,但我认为这个问题是无关紧要的。也许EventModel表示“工作包”的完成处理......感谢任何想法,评论家...... 克里斯
答案 0 :(得分:2)
一堆小调:
如果你正在使用一些内部使用ThreadPool的.NET API,那么就不能进行无限等待,因为操作系统拥有来自ThreadPool的线程,这些线程意味着“短暂”使用然后返回到操作系统,这是最强大的行为。当然,操作系统可以根据需要增加线程池,如果由于长时间运行处理而最终占用它们,但更好的设计是避免这种行为。
如果你在XP上运行,你可能还想避免使用ThreadPool(操作系统级别,因此是.NET),因为它在Vista中被修复/重新签名,之后,XP版本被认为不太健壮。
如果您确实使用了ThreadPool,那么您最终会将异步工作排队,因为它已经在等待工作了。
编写自己的ThreadManager非常容易,你可以在其上找到很多例子,但是一如既往,这类事情应尽可能简单。
对于你的第三个要点,最好恢复SFTP连接,而不是终止你的整个线程。如果你杀掉一个线程(假设你的ThreadManager可以处理它,永远不会从操作系统ThreadPool中删除线程),而不是首先必须将未处理的作业返回到某个队列,感觉就像工作太多了。
答案 1 :(得分:0)
另一种方法是使用WeOnlyDo(http://www.weonlydo.com/FtpDLX.NET/ftp.sftp.ftps.ssl.net.component.asp)中的FtpDlx。它只有229美元,是完全管理的.Net 2.0库。它包括递归下载目录的方法。它使用事件来指示进度和错误,允许您跳过文件,重定向您编写它们的位置,以及检查和忽略错误。它很健壮,可以像宣传的那样工作;我们在多线程生产代码中使用它。
您可以在单独的线程中运行它,并使用事件来更新您的UI而不会阻塞。您甚至可能会发现执行下载的一个线程充分利用了您的带宽,但它可以在单独的线程中使用单独的连接正常工作。我建议您创建自己的线程而不是使用ThreadPool,因为您将要使用回调,并且线程往往会长时间运行。
答案 2 :(得分:0)
使用SFTP和.NET与tamir.ssh和multithead你可以这样做:
Task.Factory.StartNew(()=> new Main()。run());
1.1从SFT下载文件
1.2从SFTP上传文件
MAIN课程
公共课主 { 任务[] _tasks = null;
public void run()
{
_tasks = new Task[2];
var task = new Task(() => Download(),TaskCreationOptions.LongRunning);
task.Start();
_tasks[0] = task;
var task = new Task(() => Download(),TaskCreationOptions.LongRunning);
task.Start();
_tasks[1] = task;
Task.WaitAny(_tasks);
}
private void Upload()
{ Sftp _Sftp = null;
while (true)
{
filesToUpload = GetFiles(Sourcepath);
Parallel.ForEach(filesToUpload, _fileData =>
{
if(!_Sftp.Insconnected)
{
_Sftp = new Sftp(Host, User,Password);
_Sftp.Connect();
}
if(_Sftp.Connected)
_Sftp.Put(_fileData.Path, DestinyPath);
});
}
}
public void Download()
{
Sftp _Sftp = null;
While(true)
{
if(!_Sftp.Connected)
{
_Sftp = new Sftp(Host, User,Password);
_Sftp.Connect();
}
if(_Sftp.Connected)
{
ArrayList fileToDownload = _Sftp.GetFileList(_Instance.Sourcepath);
Parallel.ForEach(fileToDownload, _fileData =>
{
_Sftp.Get(Sourcepath + "/" + _fileData.Name,DestinyPath);
});
}
}
}