- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
使用 FtpWebRequest 类并分配 BackgroundWorker 上传文件。并正常工作但现在我想从目录及其子目录上传文件。
我创建了一个名为“FtpUploading”的组件,其中定义了 private void 函数“FtpUploading_DoWork”
同样应该从 Windows 窗体应用程序调用...如果目录中有单个文件则工作文件但如果有多个文件和子目录...它将无法工作。
private void FtpUploading_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker bw = sender as BackgroundWorker;
FtpSettings ftpDet = e.Argument as FtpSettings;
string UploadPath = String.Format("{0}/{1}{2}", ftpDet.Host, ftpDet.TargetFolder == "" ? "" : ftpDet.TargetFolder + "/", Path.GetFileName(ftpDet.SourceFile));
if (!UploadPath.ToLower().StartsWith("ftp://"))
UploadPath = "ftp://" + UploadPath;
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(UploadPath);
request.UseBinary = true;
request.UsePassive = ftpDet.Passive;
request.Method = WebRequestMethods.Ftp.UploadFile;
request.Credentials = new NetworkCredential(ftpDet.Username, ftpDet.Password);
long FileSize = new FileInfo(ftpDet.SourceFile).Length;
string mFileName = new FileInfo(ftpDet.SourceFile).Name;
string FileSizeDescription = GetFileSize(FileSize);
int ChunkSize = 4096, NumRetries = 0, MaxRetries = 50;
long SentBytes = 0;
byte[] Buffer = new byte[ChunkSize];
using (Stream requestStream = request.GetRequestStream())
{
using (FileStream fs = File.Open(ftpDet.SourceFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
int BytesRead = fs.Read(Buffer, 0, ChunkSize);
while (BytesRead > 0)
{
try
{
if (bw.CancellationPending)
return;
requestStream.Write(Buffer, 0, BytesRead);
SentBytes += BytesRead;
string SummaryText = String.Format(mFileName + " => Transferred {0} / {1}", GetFileSize(SentBytes), FileSizeDescription);
bw.ReportProgress((int)(((decimal)SentBytes / (decimal)FileSize) * 100), SummaryText);
}
catch (Exception ex)
{
Debug.WriteLine("Exception: " + ex.ToString());
if (NumRetries++ < MaxRetries)
{
fs.Position -= BytesRead;
}
else
{
throw new Exception(String.Format("Error occurred during upload, too many retries. \n{0}", ex.ToString()));
}
}
BytesRead = fs.Read(Buffer, 0, ChunkSize);
}
}
}
using (FtpWebResponse response = (FtpWebResponse)request.GetResponse())
System.Diagnostics.Debug.WriteLine(String.Format("Upload File Complete, status {0}", response.StatusDescription));
}
public static string GetFileSize(long numBytes)
{
string fileSize = "";
if (numBytes > 1073741824)
fileSize = String.Format("{0:0.00} Gb", (double)numBytes / 1073741824);
else if (numBytes > 1048576)
fileSize = String.Format("{0:0.00} Mb", (double)numBytes / 1048576);
else
fileSize = String.Format("{0:0} Kb", (double)numBytes / 1024);
if (fileSize == "0 Kb")
fileSize = "1 Kb"; // min.
return fileSize;
}
//调用函数
private void recursiveDirectory(string dirPath, string uploadPath)
{
string[] files = Directory.GetFiles(dirPath, "*.*");
string[] subDirs = Directory.GetDirectories(dirPath);
foreach (string file in files)
{
if (this.ftpUploading1.IsBusy)
{
// this.ftpUploading1.CancelAsync();
// this.btnFtp.Text = "Upload";
Thread.Sleep(50);
break;
}
else
{
ftpSet.TargetFolder = uploadPath;
ftpSet.SourceFile = file;
this.toolStripProgressBar1.Visible = true;
this.ftpUploading1.RunWorkerAsync(ftpSet);
this.btnFtp.Text = "Cancel";
}
}
foreach (string subDir in subDirs)
{
ftpClient.createDirectory(uploadPath + "/" + Path.GetFileName(subDir));
recursiveDirectory(subDir, uploadPath + "/" + Path.GetFileName(subDir));
}
}
最佳答案
您在启动 ync 任务后立即检查 IsBusy
,如果它是 true
,您将打破几乎总是如此的循环。这是怎么回事。
删除该条件将导致您在评论中提到的错误。因此,您应该等待任务完成,或者在 FtpUploading_DoWork
中实现一个循环。
第三个(也是最好的)选项是使用任务
。 Task
支持 ContinueWith()
,这正是您所需要的。
我将在这里解释第一个解决方案,因为它只需要对您现有的代码进行很少的更改。此外,这只是为了让您大致了解同步过程。您可能需要进一步完善代码。
您需要一个 WaitHandle
,以便 FtpUploading_DoWork
告诉 recursiveDirectory
它何时完成其工作。为此,我们将使用 ManualResetEvent
。一旦您 Reset
ManualResetEvent,它将等待对 WaitOne
的调用,直到另一个线程在同一个 ManualResetEvent 上调用 Set
。
回到工作中,将 ManualResetEvent
添加到您的类中:
System.Threading.ManualResetEvent waitForUpload = new
System.Threading.ManualResetEvent(false);
更改 recursiveDirectory
中的第一个 for
:
foreach (string file in files)
{
ftpSet.TargetFolder = uploadPath;
ftpSet.SourceFile = file;
this.toolStripProgressBar1.Visible = true;
waitForUpload.Reset();
this.ftpUploading1.RunWorkerAsync(ftpSet);
this.btnFtp.Text = "Cancel";
waitForUpload.WaitOne();
while (this.ftpUploading1.IsBusy)
{
Thread.Sleep(100); // This is for the case if the WaitHandle is Set
// but the BackgroundWorker is still busy,
// which should not take so long
}
}
并更改 FtpUploading_DoWork
:
private void FtpUploading_DoWork(object sender, DoWorkEventArgs e)
{
try
{
// Existing code inside the method
}
finally
{
waitForUpload.Set();
}
}
关于c# - 在 C# 中使用 FtpWebRequest 和 BackgroundWorker 递归上传文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18440473/
在我的应用程序中,我在添加到我的列表框之前通过打开的 Wireshark 进程检查我的文件。这是添加目录单击事件,它获取根文件夹并检查此文件夹和子文件夹中的所有文件: private void btn
我有一个使用异步后台工作程序执行批处理文件的程序。这是代码: public static void Execute(CmdObj obj, bool batch) { CmdObj = obj
我正在尝试在项目中执行数据库密集型任务。这是一个演练: 我们需要搜索我们的 worker 数据库,我们称之为 Locums,并找到一个适合特定工作的人。当我们决定处理 x 个作业时,此过程开始。因此,
首先,我还是个初学者,如果您能耐心一点,我将不胜感激:) 今天我一直在为这件事绞尽脑汁。 问题是,我想运行三个不同的后台程序。但是我想等到一个运行完再运行下一个,依此类推。 每个后台 worker 都
我需要确保 BackgroundWoker 在被调用之前不忙,所以我检查 IsBusy 并调用 CancelAsync如果是: if (bgWorker.IsBusy)
我的目标是: 用户在组合框中输入完整或部分计算机名 按钮单击事件启动后台工作程序将计算机名传递给 DoWork 方法 DoWork 方法在 ActiveDirectory 中搜索计算机名并将集合传递给
每次我的代码需要与网络或数据库通信时,我都会使用后台工作人员,我是否可以使用太多,执行这些任务的正确方法是什么? 如果我不使用后台工作程序,则在远程主机关闭等情况下,gui会锁定,因此使用后台工作程序
关于 BGW 长期运行的任何想法建议? 最佳答案 是的 :)。在 BackgroundWorker 或 ThreadPool 中进行长时间运行的操作并没有本质上的错误……如果由于长时间运行的操作而导致
学习构建多线程 WPF 应用程序我读到了一些使用 BackgroundWorker 的限制,这对我来说不是很清楚。请帮我理解: 如果我不仅想要一个线程在 UI 的幕后工作,而且可能有多个线程,它们彼此
问题:重新使用 .NET Backgroundworker,有没有办法让异常正常传递回主线程? 背景: 目前在我的 WinForms 应用程序中,我有通用异常句柄,如果(a)自定义应用程序异常然后呈现
在尝试实现一个简单的 BackgroundWorker 时,我遇到了臭名昭著的“跨线程操作无效”异常。我花了几个小时阅读我能找到的关于这个主题的所有内容,包括关于 SO 的许多相关问题,但我就是不明白
有没有办法缩短我的 BackgroundWorker.CancellationPending 检查点? 例如,有没有办法像下面的示例代码一样封装return: //REAL CODE (CURRENT
嗨,我在处理完成后,无法将在BackgroundWorker的DoWork处理程序内部生成的图像数据分配给图像对象。我收到一条错误消息,指出“调用线程无法访问此对象,因为其他线程拥有它”。错误行是 P
如何获得有意义的BackgroundWorker.Error当DoWork必须调用可能引发异常的委托(delegate)? 我正在实现一个静态 MsgBox公开向用户传达自定义消息的各种方式(使用自定
我知道您可以在首次启动 backgroundworker 时通过 RunWorkerAsync 函数调用传递参数,但是您可以在它已经启动后向它传递数据吗?或者我是否需要创建自己的并发形式来处理从不同线
我有一个风格问题,关于我应该在 Windows 窗体应用程序上使用的后台线程实现的选择。目前,我的表单上有一个 BackgroundWorker,它具有无限 (while(true)) 循环。在此循环
我正在尝试在 .NET 1.1 中实现一个 BackgroundWorker(因为没有任何东西),而且我不太精通线程和委托(delegate)。 现在我有一个名为 BackgroundWorker 的
foreach (string file in listToConvert) { BackgroundWorker backgroundWorker = new BackgroundWorke
我正在制作我的第一个 C# GUI。它使用 BackgroundWorker 来运行计算量大的模拟。模拟会定期报告(通过 ProgressChanged 事件)需要在 GUI 中显示的大量信息。 GU
我想从一个表单启动一个后台 worker 。 private void button2_Click(object sender, EventArgs e) { back
我是一名优秀的程序员,十分优秀!