我正在尝试通过从Google Drive / Dropbox / FTP等各种存储库导入DLL来部署Windows服务中的DLL。
但是,在实例化任何新DLL之前,我希望先关闭以前正在运行的实例。
在这个过程中,我使用了任务和反射。
我无法弄清楚如何取消任务,该任务在运行时实例化DLL(因为实例化的dll是一个长时间运行的应用程序示例文件监视器)。
错误:
在程序集“AppDomain,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null”中,类型“AppDomain.Program+<>c__DisplayClass2”未标记为可序列化。
请注意:我已将我导入的程序集中的类Program标记为可序列化。
但是,在实例化任何新DLL之前,我希望先关闭以前正在运行的实例。
在这个过程中,我使用了任务和反射。
我无法弄清楚如何取消任务,该任务在运行时实例化DLL(因为实例化的dll是一个长时间运行的应用程序示例文件监视器)。
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken ct = cts.Token;
// 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);
问题 : 在我的应用程序检测到一个新的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(delegate)寄予厚望,但是我遇到了一个错误。以下是引发错误的简化代码版本。
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,Version=1.0.0.0,Culture=neutral,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()
请注意:我已将我导入的程序集中的类Program标记为可序列化。
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();
}
}
}
Assembly.LoadFile
? - NeddySpaghetti