Уважаемый опытный.Я разрабатываю сущность, которая позволяет пользователю асинхронно копировать несколько файлов с возможностью отмены (и также сообщать о прогрессе).Очевидно, что процесс копирования выполняется в другом потоке, отличном от потока, в котором был вызван CopyAsync.
Моя первая реализация использует FileStream.BeginRead / BeginWrite с буфером и сообщает о прогрессе в зависимости от количества использований этого буфера.
Позже, в образовательных целях, я пытался реализовать то же самое с помощью функции Win32 CopyFileEx.В конце концов я наткнулся на следующее: эта функция берет указатель на значение bool, которое рассматривается как индикатор отмены.Согласно MSDN, это значение должно быть проверено несколько раз Win32 во время операции копирования.Когда пользователь устанавливает это значение в «ложь», операция копирования отменяется.
Реальная проблема для меня состоит в том, как создать логическое значение, передать его Win32 и сделать это значение доступным для внешнего пользователя, чтобы дать емувозможность отменить операцию копирования.Очевидно, что пользователь вызовет CancelAsync (object taskId), поэтому мой вопрос о том, как получить доступ к этому логическому значению в другом потоке для моей реализации CancelAsync.
Моя первая попытка состояла в том, чтобы использовать Dictionary, где key является идентификаторомасинхронной операции и значения указывает на выделенный для слота памяти логическое значение.Когда пользователь вызывает метод «CancelAsync (object taskId)», мой класс получает указатель на эту выделенную память из словаря и записывает туда «1».
Вчера я разработал другое решение, основанное на создании boolлокальная переменная в моем методе копирования и хранения адреса этого значения в словаре до завершения операции копирования.Этот подход может быть описан в следующих строках кода (очень простой и грубый, просто чтобы проиллюстрировать идею):
class Program
{
// dictionary for storing operaitons identifiers
public Dictionary<string, IntPtr> dict = new Dictionary<string,IntPtr>();
static void Main(string[] args)
{
Program p = new Program();
p.StartTheThread(); // start the copying operation, in my
// implementation it will be a thread pool thread
}
ManualResetEvent mre;
public void StartTheThread()
{
Thread t = new Thread(ThreadTask);
mre = new ManualResetEvent(false);
t.Start(null);
GC.Collect(); // just to ensure that such solution works :)
GC.Collect();
mre.WaitOne();
unsafe // cancel the copying operation
{
IntPtr ptr = dict["one"];
bool* boolPtr = (bool*)ptr; // obtaining a reference
// to local variable in another thread
(*boolPtr) = false;
}
}
public void ThreadTask(object state)
{
// In this thread Win32 call to CopyFileEx will be
bool var = true;
unsafe
{
dict["one"] = (IntPtr)(&var); // fill a dictionary
// with cancellation identifier
}
mre.Set();
// Actually Win32 CopyFileEx call will be here
while(true)
{
Console.WriteLine("Dict:{0}", dict["one"]);
Console.WriteLine("Var:{0}", var);
Console.WriteLine("============");
Thread.Sleep(1000);
}
}
}
На самом деле я немного новичок в P / Invoke и всех небезопасных вещах, поэтому колеблюсьо последнем подходе для удержания ссылки на локальное значение в словаре и предоставления этого значения другому потоку.
Любые другие мысли о том, как выставить этот указатель на логическое значение для поддержки отмены операции копирования?