Starksoft.Net.Ftp을 사용하여 업로드에 대한 비동기 작업을 수행하고 있습니다.왜 두 개의 ManualResetEvent로 작업하면 교착 상태가 발생합니까?
그렇게 보이는 :
public void UploadFile(string filePath, string packageVersion)
{
_uploadFtpClient= new FtpClient(Host, Port, FtpSecurityProtocol.None)
{
DataTransferMode = UsePassiveMode ? TransferMode.Passive : TransferMode.Active,
FileTransferType = TransferType.Binary,
};
_uploadFtpClient.TransferProgress += TransferProgressChangedEventHandler;
_uploadFtpClient.PutFileAsyncCompleted += UploadFinished;
_uploadFtpClient.Open(Username, Password);
_uploadFtpClient.ChangeDirectoryMultiPath(Directory);
_uploadFtpClient.MakeDirectory(newDirectory);
_uploadFtpClient.ChangeDirectory(newDirectory);
_uploadFtpClient.PutFileAsync(filePath, FileAction.Create);
_uploadResetEvent.WaitOne();
_uploadFtpClient.Close();
}
private void UploadFinished(object sender, PutFileAsyncCompletedEventArgs e)
{
if (e.Error != null)
{
if (e.Error.InnerException != null)
UploadException = e.Error.InnerException;
}
_uploadResetEvent.Set();
}
당신이 볼 수 있듯이이 클래스의 상단에 전용 변수로 선언이의 으로 ManualResetEvent,이 :
private ManualResetEvent _uploadResetEvent = new ManualResetEvent(false);
음, 그 의미는 업로드가 완료 될 때까지 기다려야한다는 것입니다. 그러나 진행 상황을보고하는 데는 비동기 적이어야합니다.
이제는 정상적으로 작동합니다. 두 번째 방법을 사용하여 원하는 경우 업로드를 취소해야합니다.
public void Cancel()
{
_uploadFtpClient.CancelAsync();
}
업로드가 취소되면 서버의 디렉토리도 삭제해야합니다. 은 나도이 방법을 가지고 :
취소 할 때 업로드 완성 된 이벤트가 호출되지 않습니다으로public void DeleteDirectory(string directoryName)
{
_uploadResetEvent.Set(); // As the finished event of the upload is not called when cancelling, I need to set the ResetEvent manually here.
if (!_hasAlreadyFixedStrings)
FixProperties();
var directoryEmptyingClient = new FtpClient(Host, Port, FtpSecurityProtocol.None)
{
DataTransferMode = UsePassiveMode ? TransferMode.Passive : TransferMode.Active,
FileTransferType = TransferType.Binary
};
directoryEmptyingClient.Open(Username, Password);
directoryEmptyingClient.ChangeDirectoryMultiPath(String.Format("/{0}/{1}", Directory, directoryName));
directoryEmptyingClient.GetDirListAsyncCompleted += DirectoryListingFinished;
directoryEmptyingClient.GetDirListAsync();
_directoryFilesListingResetEvent.WaitOne(); // Deadlock appears here
if (_directoryCollection != null)
{
foreach (FtpItem directoryItem in _directoryCollection)
{
directoryEmptyingClient.DeleteFile(directoryItem.Name);
}
}
directoryEmptyingClient.Close();
var directoryDeletingClient = new FtpClient(Host, Port, FtpSecurityProtocol.None)
{
DataTransferMode = UsePassiveMode ? TransferMode.Passive : TransferMode.Active,
FileTransferType = TransferType.Binary
};
directoryDeletingClient.Open(Username, Password);
directoryDeletingClient.ChangeDirectoryMultiPath(Directory);
directoryDeletingClient.DeleteDirectory(directoryName);
directoryDeletingClient.Close();
}
private void DirectoryListingFinished(object sender, GetDirListAsyncCompletedEventArgs e)
{
_directoryCollection = e.DirectoryListingResult;
_directoryFilesListingResetEvent.Set();
}
, 내가 DeleteDirectory-방법으로 수동으로 ResetEvent를 설정해야합니다.
여기에서 나는 무엇을하고 있는가? 먼저 채워진 폴더를 삭제할 수 없으므로 삭제하기 위해 디렉토리의 모든 파일을 나열합니다.
이 방법 GetDirListAsync 또한 내가 양식을 동결하고 싶지 않아 나는 다른 으로 ManualResetEvent 필요 의미 비동기입니다.
이 ResetEvent는 _directoryFilesListingResetEvent입니다. 위의 _uploadResetEvent과 같이 선언되었습니다.
이제는 _directoryFilesListingResetEvent의 WaitOne 호출로 이동 한 다음 문제가 발생합니다. 교착 상태이 나타나고 양식이 정지됩니다. (코드에 표시했습니다.)
왜 그런가요? _uploadResetEvent.Set()의 호출을 이동하려고 시도했지만 변경되지 않았습니다. 누구에게이 문제가 보이나요?
아무런 업로드없이 DeleteDirectory -method 만 호출하면 잘 작동합니다. 난 둘 다 ResetEvents 같은 리소스 또는 무언가를 사용하여 자신을 중복, 문제는 것 같아요, 나도 몰라.
도움 주셔서 감사합니다.
업로드가 삭제하려는 디렉토리에 잠금을 설정할 수 있습니까? – jaywayco
좋은 점은, 내가 거기에서 만들었지 만, "CancelAsync"가 그것을 관리하지 않아야한다는 것입니까? –
cancelasync가 uploadfinished 이벤트를 트리거합니까? 업로드 클라이언트가 닫히지 않고 리소스에 걸려있을 수없는 경우 – jaywayco