Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/336.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
停止/处置/取消任务C#_C#_.net_Task Parallel Library_Task_Cancellationtokensource - Fatal编程技术网

停止/处置/取消任务C#

停止/处置/取消任务C#,c#,.net,task-parallel-library,task,cancellationtokensource,C#,.net,Task Parallel Library,Task,Cancellationtokensource,我试图通过从各种存储库(如google drive/dropbox/ftp等)导入DLL,在windows服务中部署DLL 但在实例化任何新的DLL之前,我希望关闭以前运行的实例 我在这里使用任务和反思 我无法确定如何取消在运行时实例化DLL的任务(因为实例化的DLL是一个长时间运行的应用程序示例文件查看器..) 问题:我想在我的应用程序检测到新的dll并尝试通过此任务代码执行之前取消任务t 编辑 我删除了中断的取消令牌代码。这是带有取消令牌的实际代码 CancellationToken

我试图通过从各种存储库(如google drive/dropbox/ftp等)导入DLL,在windows服务中部署DLL

但在实例化任何新的DLL之前,我希望关闭以前运行的实例

我在这里使用任务和反思

我无法确定如何取消在运行时实例化DLL的任务(因为实例化的DLL是一个长时间运行的应用程序示例文件查看器..)

问题:我想在我的应用程序检测到新的dll并尝试通过此任务代码执行之前取消任务t

编辑 我删除了中断的取消令牌代码。这是带有取消令牌的实际代码

    CancellationTokenSource cts = new CancellationTokenSource();
    CancellationToken ct = cts.Token;

if (t != null)
        {
            cts.Cancel();
            try
            {
                ct.ThrowIfCancellationRequested();
            }
            catch (Exception ex)
            {

                cts.Dispose();
                t.Dispose();
            }

        }

                // instantiate the dll though reflection
        t = Task.Factory.StartNew(() =>
        {
            try
            {
                Assembly assembly = Assembly.LoadFile(Directory.GetCurrentDirectory() + @"\" + dllName);
                Type type = assembly.GetType("myclass.Program");

                MethodInfo minfo = type.GetMethod("Main", BindingFlags.Public | BindingFlags.NonPublic |
                          BindingFlags.Static | BindingFlags.Instance);
                minfo.Invoke(Activator.CreateInstance(type), null);

            }
            catch (Exception ex)
            {

                log.Error(ex.ToString());
            }
        }, cts.Token);
我的想法是,如果我能够以某种方式取消并处理保存实例化上下文的任务,那么程序集将被释放,然后我将能够更新程序集并通过任务再次重新实例化它

我知道我哪里出了问题,请解释一下

编辑

我对assemblyDomain.DoCallBack(代表)寄予厚望。但是我犯了一个错误。下面是抛出错误的代码的低调版本

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading.Tasks;
using System.Reflection;


namespace AppDomain
{
    [Serializable]
    class Program
    {
        static System.AppDomain assemblyDomain = null;

        static void Main(string[] args)
        {

            var inp = "go";

            while (inp.ToString().ToLower().Trim() != "stop")
            {
                start();
                inp = Console.ReadLine();
            }

        }

        private static void start()
        {


            //Check if appdomain and assembly is already loaded
            if (assemblyDomain != null)
            {
                //unload appDomain and hence the assembly
                System.AppDomain.Unload(assemblyDomain);

                //Code to download new dll
            }

            string cwd = System.AppDomain.CurrentDomain.BaseDirectory;

            string sourceFileName = @"C:\Users\guest\Documents\visual studio 2010\Projects\DotNetTraining\Lecture 1 - dotNetProgramExecution\bin\Debug\Lecture 1 - dotNetProgramExecution.exe";

            string dllName = "Lecture 1 - dotNetProgramExecution.exe";

            // copy the file
            if (File.Exists(cwd + dllName))
            {
                File.Delete(cwd + dllName);
            }

            File.Copy(sourceFileName, cwd + dllName);

            assemblyDomain = System.AppDomain.CreateDomain("assembly1Domain", null);
            assemblyDomain.DoCallBack(() =>
               {
                   var t = Task.Factory.StartNew(() =>
                   {
                       try
                       {

                           string sss = "";
                           Assembly assembly = Assembly.LoadFile(Directory.GetCurrentDirectory() + @"\" + dllName);
                           Type type = assembly.GetType("Lecture_1___dotNetProgramExecution.Program");

                           MethodInfo minfo = type.GetMethod("Main", BindingFlags.Public | BindingFlags.NonPublic |
                                     BindingFlags.Static | BindingFlags.Instance);
                           minfo.Invoke(Activator.CreateInstance(type), null);



                           //        //var pathToDll = @"assembly path";
                           //        //var dllName = "assembly name";
                           //        var assembly = Assembly.LoadFile(Directory.GetCurrentDirectory() + @"\" + dllName);
                           //        var targetAssembly = assembly.CreateInstance("Lecture_1___dotNetProgramExecution.Program");
                           //        Type type = targetAssembly.GetType();
                           //        MethodInfo minfo = type.GetMethod("Main", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance);
                           //        minfo.Invoke(targetAssembly, null);

                       }
                       catch (Exception ex)
                       {

                           Console.WriteLine(ex.ToString());
                       }
                   });
               });
        }
    }
}

错误:
在程序集“AppDomain,版本=1.0.0.0,区域性=中立,PublicKeyToken=null”中键入“AppDomain.Program+c__DisplayClass2”未标记为可序列化。

堆栈跟踪:

at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at AppDomain.Program.start() in c:\users\guest\documents\visual studio 2010\Projects\DotNetTraining\AppDomain\Program.cs:line 58
   at AppDomain.Program.Main(String[] args) in c:\users\guest\documents\visual studio 2010\Projects\DotNetTraining\AppDomain\Program.cs:line 24
   at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
   at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
   at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
   at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()
请注意:我已将im导入程序集中的类程序标记为可序列化

namespace Lecture_1___dotNetProgramExecution
{
    [Serializable]
    class Program
    {
        static void Main()
        {
更新:

动态拉动组件的代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Threading;

namespace Lecture_1___dotNetProgramExecution
{
    [Serializable]
    class Program
    {
        static void Main()
        {
            try
            {

                Task.Factory.StartNew(() =>
                {

                    while (true)
                    {
                        StringBuilder sb = new StringBuilder();
                        sb.Append("log something new yippe ");
                        // flush every 20 seconds as you do it
                        File.AppendAllText(@"C:\logs.txt", sb.ToString());
                        sb.Clear();
                        Thread.Sleep(3000);
                    }

                });



                FileSystemWatcher fsw = new FileSystemWatcher();

                fsw.Path = @"c:\watched";
                //fsw.filter = ".dll";
                fsw.Created += new FileSystemEventHandler(fsw_Created);
                fsw.BeginInit();
                //throw new FileNotFoundException();
                Console.ReadLine();

            }
            catch (Exception ex)
            {

                Task.Factory.StartNew(() =>
                {

                    while (true)
                    {
                        StringBuilder sb = new StringBuilder();
                        sb.Append("loggind froom exception log something");
                        // flush every 20 seconds as you do it
                        File.AppendAllText(@"C:\logs.txt", sb.ToString());
                        sb.Clear();
                        Thread.Sleep(1000);
                    }

                });
                Console.ReadLine();
            }
        }

        static void fsw_Created(object sender, FileSystemEventArgs e)
        {
            throw new NotImplementedException();
        }


    }
}

根据您的问题,您似乎希望卸载动态加载的程序集(如果有任何升级可用),然后重新加载最新的程序集。取消在这种情况下没有任何帮助。事实上,我没有看到你在任何地方使用取消令牌

卸载动态加载的程序集的唯一方法是首先在单独的应用程序域中加载程序集,然后在不再需要程序集时卸载应用程序域本身。因此,您应该按照以下步骤操作:

  • 创建一个新的应用程序域。保留app domain的引用,以后需要它来卸载域和程序集
  • 在新创建的应用程序域中加载程序集
  • 根据需要从新加载的程序集创建类型的实例,并执行其方法
  • 当新版本的dll可用时,卸载先前创建的应用程序域。这也将自动卸载程序集
  • 下载新部件并再次从步骤1开始
  • 有关如何在其中加载/卸载应用程序域和程序集,请参见以下内容:

    编辑:下面是AppDomain.DoCallback的代码片段

    using System;
    using System.IO;
    using System.Reflection;
    using System.Threading.Tasks;
    
    
    namespace AppDomain
    {
    [Serializable]
    class Program
    {
        static System.AppDomain assemblyDomain = null;
    
        static void Main(string[] args)
        {
    
            var inp = "go";
    
            while (inp.ToString().ToLower().Trim() != "stop")
            {
                start();
                inp = Console.ReadLine();
            }
    
        }
    
        private static void start()
        {
    
    
            //Check if appdomain and assembly is already loaded
            if (assemblyDomain != null)
            {
                //unload appDomain and hence the assembly
                System.AppDomain.Unload(assemblyDomain);
    
                //Code to download new dll
            }
    
            string cwd = System.AppDomain.CurrentDomain.BaseDirectory;
    
            string sourceFileName = @"C:\Users\deepak\Documents\visual studio 2010\Projects\ConsoleApplication1\ConsoleApplication2\bin\Debug\ConsoleApplication2.exe";
    
    
            string dllName = "ConsoleApplication2.exe";
    
            // copy the file
            if (File.Exists(cwd + dllName))
            {
                File.Delete(cwd + dllName);
            }
    
            File.Copy(sourceFileName, cwd + dllName);
    
            assemblyDomain = System.AppDomain.CreateDomain("assembly1Domain", null);
            assemblyDomain.DoCallBack(() =>
            {
                var t = Task.Factory.StartNew(() =>
                {
                    try
                    {
    
                        string sss = "";
                        string dllName1 = "ConsoleApplication2.exe";
                        Assembly assembly = Assembly.LoadFile(Directory.GetCurrentDirectory() + @"\" + dllName1);
                        Type type = assembly.GetType("Lecture_1___dotNetProgramExecution.Program");
    
                        MethodInfo minfo = type.GetMethod("Main", BindingFlags.Public | BindingFlags.NonPublic |
                                  BindingFlags.Static | BindingFlags.Instance);
                        minfo.Invoke(Activator.CreateInstance(type), null);
                    }
                    catch (Exception ex)
                    {
    
                        Console.WriteLine(ex.ToString());
                    }
                });
            });
        }
    }
    }
    
    
    using System;
    using System.Text;
    using System.Threading;
    
    namespace Lecture_1___dotNetProgramExecution
    {
    [Serializable]
    class Program
    {
        static void Main()
        {
            while (true)
            {
                StringBuilder sb = new StringBuilder();
                sb.Append("log something new yippe ");
                // flush every 20 seconds as you do it
                //File.AppendAllText(@"C:\logs.txt", sb.ToString());
                Console.WriteLine(sb.ToString());
                sb.Clear();
                Thread.Sleep(3000);
            }
        }
    }
    }
    

    这是一个缓慢的操作
    Assembly.LoadFile
    ?如果您试图部署更新的程序集,我认为您需要将程序集加载到单独的
    AppDomain
    中,以使它们能够卸载。您基本上关闭了
    AppDomain
    来卸载程序集,并创建一个新程序集来加载新程序集。为什么不调用
    cts.Cancel()
    ?cts.Cancel不起作用。@Enigmativity:我不想这样做。我想保留在应用程序的上下文中,删除旧TAK->然后删除旧程序集->然后引入新程序集(通过下载/复制到我的本地bin)->再次触发任务代码,这样现在新程序集被实例化,旧上下文被销毁。我明白你的意思,但我认为我的理解有点模糊,现在仍然如此。我已经更新了问题。请看一看。我会查看应用程序域链接,您根本不需要取消令牌。一旦我有权访问我的笔记本电脑,我会用代码编辑我的帖子。在我读到将组件加载到单独的应用程序域的功能后,我做了完全相同的事情。但几分钟后,我的上面发现有一个更新的版本可用。。。上面的代码再次被触发->我成功卸载了应用程序域->然后当我尝试从当前bin中删除旧的dll时,它抛出一个错误,说程序集“对路径'mydll.exe'的访问被拒绝”。我能够解决这个问题。程序集在单独的域中加载正常,但类型实例是由在当前域上下文中运行的代码创建的,该代码也在当前域中加载程序集。AppDomain.DoCallBack成功了。请参阅我上面文章中的更新代码。我已经为动态导入的dll添加了代码。请看一看。
    using System;
    using System.IO;
    using System.Reflection;
    using System.Threading.Tasks;
    
    
    namespace AppDomain
    {
    [Serializable]
    class Program
    {
        static System.AppDomain assemblyDomain = null;
    
        static void Main(string[] args)
        {
    
            var inp = "go";
    
            while (inp.ToString().ToLower().Trim() != "stop")
            {
                start();
                inp = Console.ReadLine();
            }
    
        }
    
        private static void start()
        {
    
    
            //Check if appdomain and assembly is already loaded
            if (assemblyDomain != null)
            {
                //unload appDomain and hence the assembly
                System.AppDomain.Unload(assemblyDomain);
    
                //Code to download new dll
            }
    
            string cwd = System.AppDomain.CurrentDomain.BaseDirectory;
    
            string sourceFileName = @"C:\Users\deepak\Documents\visual studio 2010\Projects\ConsoleApplication1\ConsoleApplication2\bin\Debug\ConsoleApplication2.exe";
    
    
            string dllName = "ConsoleApplication2.exe";
    
            // copy the file
            if (File.Exists(cwd + dllName))
            {
                File.Delete(cwd + dllName);
            }
    
            File.Copy(sourceFileName, cwd + dllName);
    
            assemblyDomain = System.AppDomain.CreateDomain("assembly1Domain", null);
            assemblyDomain.DoCallBack(() =>
            {
                var t = Task.Factory.StartNew(() =>
                {
                    try
                    {
    
                        string sss = "";
                        string dllName1 = "ConsoleApplication2.exe";
                        Assembly assembly = Assembly.LoadFile(Directory.GetCurrentDirectory() + @"\" + dllName1);
                        Type type = assembly.GetType("Lecture_1___dotNetProgramExecution.Program");
    
                        MethodInfo minfo = type.GetMethod("Main", BindingFlags.Public | BindingFlags.NonPublic |
                                  BindingFlags.Static | BindingFlags.Instance);
                        minfo.Invoke(Activator.CreateInstance(type), null);
                    }
                    catch (Exception ex)
                    {
    
                        Console.WriteLine(ex.ToString());
                    }
                });
            });
        }
    }
    }
    
    
    using System;
    using System.Text;
    using System.Threading;
    
    namespace Lecture_1___dotNetProgramExecution
    {
    [Serializable]
    class Program
    {
        static void Main()
        {
            while (true)
            {
                StringBuilder sb = new StringBuilder();
                sb.Append("log something new yippe ");
                // flush every 20 seconds as you do it
                //File.AppendAllText(@"C:\logs.txt", sb.ToString());
                Console.WriteLine(sb.ToString());
                sb.Clear();
                Thread.Sleep(3000);
            }
        }
    }
    }