開源跨平臺運行服務(wù)插件TaskCore.MainForm
本次將要很大家分享的是一個跨平臺運行的服務(wù)插件 - TaskCore.MainForm,此框架是使用.netcore來寫的,現(xiàn)在netcore已經(jīng)支持很多系統(tǒng)平臺運行了,所以將以前的Task.MainForm改良成跨平臺的服務(wù)共大家使用和相互交流;本來這篇應(yīng)該分享的是nginx+iis+redis+Task.MainForm構(gòu)建分布式架構(gòu)后續(xù)文章,但使用.netcore來定義一個服務(wù)插件和跨平臺測試經(jīng)過讓我既興奮又頭痛,不說了下次再分享分布式后續(xù)文章吧;那么開始今天的分享內(nèi)容,希望各位多多支持:
. 框架結(jié)構(gòu)介紹及運行效果圖
. 如何生成nuget包和使用開源框架TaskCore.MainForm
. win7和ubuntu16.04運行TaskCore.MainForm的兩種方式和測試截圖(也可認(rèn)為.netcore項目在win7和ubuntu系統(tǒng)運行的兩種方式)
. 框架代碼解讀及感悟
下面一步一個腳印的來分享:
. 框架結(jié)構(gòu)介紹及運行效果圖
首先,咋們先來認(rèn)識下項目源碼的工程目錄結(jié)構(gòu)如圖:

結(jié)構(gòu)看上去應(yīng)該夠清晰了,源碼文件量也很少,不過的確實現(xiàn)了動態(tài)加載程序集dll來執(zhí)行任務(wù),后面會給出相應(yīng)的執(zhí)行截圖,我們再來看下TaskCore.MainForm項目通過vs2015生成之后Bin文件夾中的文件如圖:

如果安裝了.netcore sdk的話在windows上您只需要上面截圖的文件就能運行插件了;再來我們在已經(jīng)安裝過core sdk的win7系統(tǒng)上執(zhí)行一下如下命令dotnet TaskCore.MainForm.dll就能看到如圖的效果:

沒錯這就是插件運行起來的效果圖,因為.netcore現(xiàn)目前暫時沒有提供類似于winform那樣的皮膚界面效果,所有只能通過命令行來做跨平臺運行程序
. 如何生成nuget包和使用TaskCore.MainForm
首先,我們要明確服務(wù)是由兩部分構(gòu)成(TaskCore.MainForm和TaskCore.Plugin);TaskCore.MainForm主要用來運行程序,TaskCore.Plugin用來作為子任務(wù)需要繼承的父類插件;當(dāng)我們下載TaskCore.MainForm運行包之后(如圖2結(jié)構(gòu)),我們還需要做的就是繼承TaskCore.Plugin.dl中的TPlugin這個類,來重寫自己的任務(wù)內(nèi)容,因此我們新建一個項目取名為:TaskCore.Test,再來我們通過vs2015引用功能直接添加TaskCore.MainForm運行包中的TaskCore.Plugin.dl引用,這個時候會提示一個錯誤:

錯誤意思是沒法加載netcore版本的dll,因此這種直接在vs項目中引用方式添加dll依賴不行,需要通過nuget來添加依賴包(.netcore對類庫的引用目前只能通過nuget來安裝依賴,這個需要注意),所以我這里把TaskCore.Plugin項目通過dotnet pack命令來生成nuget包,然后以便我TaskCore.Test項目中來使用;
如何生成nuget包(win7系統(tǒng)dotnet命令來生成包的過程和下載):
直接在vs中右鍵您需要打包的類庫項目-》選擇"在資源管理器中打開文件夾"-》這樣就到了您類庫的根目錄,然后退到類庫根目錄的上一級文件夾中-》按住鍵盤”shift"鍵并同時鼠標(biāo)右鍵要打包類庫的項目文件件(我這里是TaskCore.Plugin文件夾)-》選擇“在此處打開命令窗體” 這個時候就進(jìn)入了cmd命令窗體,當(dāng)然有些朋友直接喜歡直接先cmd再來找對應(yīng)的磁盤,反正我覺得第一種更快點(不同人不同選擇吧),下面看下操作截圖:

由上圖可以看到,通過命令生成了nupkg文件,這文件就是咋們需要在項目中下載安裝的TaskCore.Plugin插件包;接下來我們來在TaskCore.Test項目中安裝這個插件如下步奏,右鍵TaskCore.Plugin項目中的“引用”-》選擇“管理nuget程序包”-》然后選擇右上角的這個圖標(biāo)

-》選擇“Nuget包管理器”-》“程序包源”-》

-》然后選擇新創(chuàng)建的包源,下面設(shè)置如圖

這里的“源(S)”指定的本地路徑就是剛才我們生成的nupkg文件文件的磁盤(當(dāng)然我這里是吧剛才pack命令生成的文件復(fù)制到了MyNugPackage文件夾中方便測試)-》然后點擊”確定“按鈕-》然后在返回到

選擇我們的包源MyNugPackage-》再瀏覽這里就能看到我們創(chuàng)建的nuget包了

-》選擇并安裝-》好安裝好后我們可以查看“引用”下面有了如下變化

并且project.json文件中自動添加了依賴項:

好了到我們的TaskCore.Test項目中就可以使用Task.Plugin包里面的方法很類等信息了;
使用TaskCore.MainForm:
由上面的操作TaskCore.Test項目已經(jīng)安裝了Task.Plugin包,那么我們在項目中分別創(chuàng)建3個子類并繼承自Task.Plugin包的父類TPlugin并重寫方法TPlugin_Load(),對應(yīng)文件名稱分別為:BlogsObj.cs,BlogsObj01.cs,BlogsObj02.cs,分別添加入下代碼內(nèi)容:
BlogsObj.cs:
namespace TaskCore.Test
{
// This project can output the Class library as a NuGet Package.
// To enable this option, right-click on the project and select the Properties menu item. In the Build tab select "Produce outputs on build".
public class BlogsObj : TPlugin
{
public BlogsObj()
{
}
public override void TPlugin_Load()
{
var sbLog = new StringBuilder(string.Empty);
try
{
sbLog.Append($"這里是BlogsObj,獲取配置文件:{this.XmlConfig.Name}");
//代碼塊
//
new WriteLog()._WriteLog($"{DateTime.Now}測試引用nuget包");
}
catch (Exception ex)
{
sbLog.Append($"異常信息:{ex.Message}");
}
finally
{
PublicClass._WriteLog(sbLog.ToString(), this.XmlConfig.Name);
}
}
}
}
BlogsObj01.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TaskCore.Plugin;
namespace TaskCore.Test
{
// This project can output the Class library as a NuGet Package.
// To enable this option, right-click on the project and select the Properties menu item. In the Build tab select "Produce outputs on build".
public class BlogsObj01 : TPlugin
{
public BlogsObj01()
{
}
public override void TPlugin_Load()
{
var sbLog = new StringBuilder(string.Empty);
try
{
sbLog.Append($"這里是BlogsObj01,獲取配置文件:{this.XmlConfig.Name}");
//代碼塊
//
}
catch (Exception ex)
{
sbLog.Append($"異常信息:{ex.Message}");
}
finally
{
//Console.WriteLine($"這里是Blogs,獲取配置文件:{this.XmlConfig.Name}");
PublicClass._WriteLog(sbLog.ToString(), this.XmlConfig.Name);
}
}
}
}
BlogsObj02.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using TaskCore.Plugin;
namespace TaskCore.Test
{
// This project can output the Class library as a NuGet Package.
// To enable this option, right-click on the project and select the Properties menu item. In the Build tab select "Produce outputs on build".
public class BlogsObj02 : TPlugin
{
public BlogsObj02()
{
}
public override void TPlugin_Load()
{
//Console.WriteLine($"這里是Blogs,獲取配置文件:{this.XmlConfig.Name}");
PublicClass._WriteLog($"這里是BlogsObj02,獲取配置文件:{this.XmlConfig.Name}", this.XmlConfig.Name);
}
}
}
好了測試代碼寫完,咋們生成一下,然后把這個TaskCore.Test.dll拷貝到TaskCore.MainForm運行包中,還需要在PluginXml文件夾中分別創(chuàng)建繼承TPlugin的子類的配置文件對應(yīng)的截圖如(注:這里xml配置文件名稱必須和子類名稱一樣):

配置文件內(nèi)容如BlogsObj.xml:
<!-- 1.xml配置模板 2.utf-8文件 3.復(fù)制到程序根目錄下面PluginXml文件夾下 4.每個任務(wù)建議創(chuàng)建和程序dll名稱相同xml配置文件 --> <TaskMain> <!--固定:執(zhí)行任務(wù)時間計時器(分鐘)--> <Timer>1</Timer> <!--固定:任務(wù)名稱--> <Name>獲取博客信息</Name> <!--固定:賬號--> <UserName></UserName> <!--固定:密碼--> <UserPwd></UserPwd> <!--固定:key--> <ApiKey></ApiKey> <!--固定:key--> <ApiUrl></ApiUrl> <!--固定:是否關(guān)閉任務(wù) 1:是 0:否--> <CloseTask>0</CloseTask> <!--固定:描述--> <Des>獲取博客信息</Des> <!--自定義:其他配置信息--> <Other> <ShenNiuBuXing3>神牛步行3</ShenNiuBuXing3> </Other> </TaskMain>
最后在CrossFiles.xml配置文件中添加TaskCore.Test.dll文件名稱如:
<!-- CrossFiles指定對應(yīng)任務(wù)的dll文件,必須存在的文件 --> <TaskMain> <File>TaskCore.Test.dll</File> </TaskMain>
好了完成了,我們在windows開發(fā)環(huán)境上運行看下效果圖:

到這里我們來簡單總結(jié)下怎么使用TaskCore.MainForm插件,在自己項目中安裝TaskCore.Plugin的nuget包-》重寫父類TPlugin的TPlugin_Load()方法-》生成自己的項目,拷貝項目的dll到TaskCore.MainForm運行包中-》在運行包中PluginXml文件夾中增加任務(wù)子類相同類名的xml文件并配置如上的配置信息-》增加CrossFiles.xml中的任務(wù)dll文件配置-》使用命令dotnet TaskCore.MainForm.dll運行服務(wù)插件,挺簡單的吧
. win7和ubuntu16.04運行TaskCore.MainForm的兩種方式和測試截圖(也可認(rèn)為.netcore項目在win7和ubuntu系統(tǒng)運行的兩種方式)
由于環(huán)境影響,這里跨平臺運行測試我只測試win7和ubuntu16.04,其他系統(tǒng)的發(fā)布測試希望朋友們在使用過程中得到結(jié)果告知我下謝謝;先來講在win7中運行:
1. 安裝了netcore sdk環(huán)境的發(fā)布運行
安裝了sdk后直接可以在cmd命令中dotnet TaskCore.MainForm.dll來運行服務(wù),開篇上面講解的示例都是在安裝了sdk后的截圖,服務(wù)運行所需要的文件如圖:

就只有這些文件(當(dāng)然程序需要的某些平臺依賴項使用的是安裝的sdk中的文件,所以看起來很少實際應(yīng)該包含netcore sdk里面的文件才能運行),通過命令運行的效果圖:

2. 未安裝netcore sdk環(huán)境的發(fā)布運行
在為安裝sdk平臺上系統(tǒng)上運行才是重點,這樣才可以說是跨平臺;首先,為了更好看效果我們復(fù)制一份如圖的兩個文件到TaskCore.MainForm01文件夾中:

沒錯,只需要這兩個文件,然后我們需要修改project.json文件的內(nèi)容如下注釋的地方:
{
"version": "1.0.0-*",
"buildOptions": {
"emitEntryPoint": true
},
"dependencies": {
"Microsoft.NETCore.App": {
//"type": "platform", 跨平臺發(fā)布需要注釋
"version": "1.0.0"
},
"System.IO.FileSystem": "4.0.1",
"System.Reflection": "4.1.0",
"System.Text.Encoding.CodePages": "4.0.1",
"System.Threading.Timer": "4.0.1",
"System.Xml.XDocument": "4.0.11",
"TaskCore.Plugin": "1.0.0"
},
"frameworks": {
"netcoreapp1.0": {
"imports": "dnxcore50"
}
},
//跨平臺發(fā)布需要添加如下節(jié)點
"runtimes": {
"ubuntu.16.04-x64": { }, //運行在ubuntu.16.04的64位系統(tǒng)
"win7-x64": { } //運行在win7的64位系統(tǒng)
}
}
然后使用cmd分別錄入并回車運行指令dotnet restore此時TaskCore.MainForm01文件夾中會自動生成一個project.lock.json文件(大家注意看下),然后再錄入指令dotnet publish -r win7-x64,可以看到命令窗信息如:

就表示成功了,并且有返回生成運行文件的路徑,我們按照路徑找到生成的文件publish文件夾,里面沒有PluginXml配置文件夾和配置文件和測試項目TaskCore.Test.dll,我們?yōu)榱朔奖阒苯訌?fù)制上面配置好的配置文件到publish文件夾中如下截圖就是生成的發(fā)布文件:

沒錯TaskCore.MainForm01.exe這個就是自動生成的運行文件,然后我們雙擊運行效果圖:

運行成功了,有朋友會問您之前系統(tǒng)不是安裝了sdk么,這種測試能算么,我想說的是這個我通過QQ發(fā)給qq群里面的朋友@南宮亦琦(不要怪我貼出了您的昵稱)測試過了,她沒有安裝過sdk的;
ubuntu16.04運行:
1. 安裝了netcore sdk環(huán)境的發(fā)布運行
首先,我們需要把在win7上生成的項目復(fù)制到ubuntu系統(tǒng)磁盤中(我們使用上面配置好的TaskCore.MainForm包),我這里采用共享目錄的方式把文件拷貝到ubuntu系統(tǒng)磁盤上,如圖:

然后,鼠標(biāo)右鍵點擊空白地方,選擇“在終端打開”,然后在窗體中錄入如下指令dotnet TaskCore.MainForm.dll,能看到如下運行起的結(jié)果:

這個命令方式是不是很上面win7上的方式很相同,本來就是一樣的,只要安裝了.netcore sdk這種方式幾乎可以共用
2. 未安裝netcore sdk環(huán)境的發(fā)布運行
不安裝sdk環(huán)境運行才是咋們需要關(guān)注的,下面就來看下怎么生成再ubuntu系統(tǒng)上能運行的文件;我們復(fù)制一份上面的TaskCore.MainForm01項目到TaskCore.MainForm02中來測試,由于之前我們在講生成win7執(zhí)行文件時候,執(zhí)行了命令dotnet restore和dotnet publish -r win7-x64命令所以文件中有project.lock和bin文件夾,為了測試我們需要刪除掉部分文件,只剩下如圖文件,這里需要注意的是之前已經(jīng)配置過project.xml我們無需在修改了:

然后,分別執(zhí)行和生成win7運行文件幾乎相同的命令dotnet restore和dotnet publish -r ubuntu.16.04-x64不同之處在于生成的文件存放的位置不同和使用的運行環(huán)境不同,運行結(jié)果如圖:

publish文件夾中的文件就是在ubuntu系統(tǒng)執(zhí)行的文件,然后我們需要把任務(wù)配置文件夾PluginXml和測試項目TaskCore.Test.dll復(fù)制到該目錄中,再來咋們通過共享吧TaskCore.MainForm02目錄中的publish復(fù)制到ubuntu中;然后我們需要把TaskCore.MainForm02可執(zhí)行文件設(shè)置下權(quán)限,鼠標(biāo)右鍵點擊TaskCore.MainForm02可執(zhí)行文件,選擇“屬性”,再選擇“權(quán)限”選項卡,勾選“允許作為程序執(zhí)行”,如圖:

然后,我們右鍵文件夾中空白處,選擇“在終端打開”,再執(zhí)行如下命令./TaskCore.MainForm02,最后看運行效果圖:

好了,發(fā)布在ubuntu系統(tǒng)上執(zhí)行文件和運行的步奏就這些,幾乎和win7上相同
. 框架代碼解讀及感悟
怎么使用跨平臺TaskCore.MainForm任務(wù)框架講解完了,下面來具體看下主要代碼Program.cs文件中:
namespace TaskCore.MainForm
{
/// <summary>
/// author 神牛步行3
/// contact 841202396@qq.com
/// des TaskCore.MainForm跨平臺插件由神牛步行3提供
/// </summary>
public class Program
{
private static Dictionary<string, MoAssembly> dicTasks = new Dictionary<string, MoAssembly>();
public static void Main(string[] args)
{
//注冊編碼,防止亂碼
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
//初始化程序集文件
_Init();
//是否繼續(xù)開啟任務(wù),默認(rèn)沒有待執(zhí)行任務(wù),不提示
if (dicTasks.Count <= 0) { _LoopAlert("是否退出?(Y/N)"); return; }
_LoopAlert("是否開始執(zhí)行任務(wù)?(Y / N)");
//執(zhí)行任務(wù)
foreach (var item in dicTasks.Values)
{
//使用Task防止異常后相互影響
Task.Run(() =>
{
try
{
//創(chuàng)建任務(wù)對象
var tp = item.Asm.CreateInstance(item.FullName) as TPlugin;
if (!string.IsNullOrEmpty(tp.XmlConfig.TpError)) { _Alert($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm")}:{tp.XmlConfig.Name} - 異常信息:{tp.XmlConfig.TpError}"); }
else
{
//timer定時器
var timer = new Timer((param) =>
{
var msg = $"{DateTime.Now.ToString("yyyy/MM/dd HH:mm")}:{tp.XmlConfig.Name}";
try
{
var tpObj = param as TPlugin;
//是否關(guān)閉暫停任務(wù)
if (tpObj.XmlConfig.CloseTask) { return; }
_Alert($"{msg} - 開始執(zhí)行...{tp.XmlConfig.Timer}分鐘一次");
//任務(wù)入口
tpObj.TPlugin_Load();
}
catch (Exception ex) { _Alert($"{msg} - 異常信息:{ex.Message}"); }
}, tp, 0, 1000 * 60 * tp.XmlConfig.Timer);
}
}
catch (Exception ex)
{
_Alert($"{DateTime.Now.ToString("yyyy/MM/dd HH:mm")}:{item.Name} - 異常信息:{ex.Message}");
}
});
}
_LoopAlert("正在監(jiān)控執(zhí)行的任務(wù),是否退出?(Y / N)");
}
/// <summary>
/// 初始化程序集文件
/// </summary>
private static void _Init()
{
try
{
_Alert("初始化任務(wù)中...");
//獲取文件
var files = PublicClass._GetPluginFile("");
if (files.Length <= 0) { _Alert("未能找到可用的程序集,請檢查配置"); return; }
//讀取任務(wù)文件
_Alert("讀取CrossFiles.xml配置中...");
var baseAddr = Path.Combine(Directory.GetCurrentDirectory(), "PluginXml", "CrossFiles.xml");
var doc = XDocument.Load(baseAddr);
var fileables = files.AsEnumerable();
var taskFiles = new List<FileInfo>();
foreach (var item in doc.Root.Nodes())
{
var crossFile = item.ToString().ToUpper();
var choiceFiles = fileables.Where(b => crossFile.Contains(b.Name.ToUpper()));
if (!choiceFiles.Any()) { continue; }
taskFiles.AddRange(choiceFiles);
}
//展示文件信息
_Alert($"待遍歷{taskFiles.Count}個文件信息...");
foreach (var item in taskFiles.OrderBy(b => b.CreationTime))
{
var asmName = new AssemblyName($"{item.Name.Replace(".dll", "")}");
Assembly sm = Assembly.Load(asmName);
if (sm == null) { continue; }
var ts = sm.GetTypes();
//判斷特定的任務(wù)類,加入任務(wù)dic
foreach (var t in ts.Where(b => b.Name != "TPlugin" && b.GetMethod("TPlugin_Load") != null))
{
dicTasks.Add(
t.FullName,
new MoAssembly
{
Asm = sm,
FullName = t.FullName,
Name = t.Name
});
}
}
_Alert($"獲取待執(zhí)行任務(wù)量:{dicTasks.Count}個");
}
catch (Exception ex)
{
_Alert($"異常信息:{ ex.Message}");
}
}
/// <summary>
/// 消息提醒
/// </summary>
/// <param name="msg">提示信息</param>
/// <param name="isReadLine">是否需要用戶輸入指令</param>
/// <returns>用戶錄入的指令</returns>
private static string _Alert(string msg = "神牛步行3-消息提醒", bool isReadLine = false)
{
Console.WriteLine(msg);
if (isReadLine) { return Console.ReadLine(); }
return "";
}
private static void _LoopAlert(string msg = "是否開始執(zhí)行任務(wù)?(Y/N)")
{
do
{
var readKey = _Alert(msg, true);
if (readKey.ToUpper().Contains("Y")) { break; }
} while (true);
}
}
public class MoAssembly
{
public Assembly Asm { get; set; }
public string FullName { get; set; }
public string Name { get; set; }
}
}
TPlugin.cs文件中代碼:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Xml.Linq;
namespace TaskCore.Plugin
{
/// <summary>
/// 插件基類
/// </summary>
public class TPlugin : IDisposable
{
public TPlugin()
{
XmlConfig = _InitConfig();
}
#region 初始化Xml配置文件 _InitConfig +XmlConfig
/// <summary>
/// xml配置信息
/// </summary>
public XmlConfig XmlConfig;
/// <summary>
/// 初始化配置信息
/// </summary>
/// <param name="configPath">配置文件對應(yīng)路徑</param>
/// <returns></returns>
public virtual XmlConfig _InitConfig(string configPath = "")
{
XmlConfig config = new XmlConfig();
config.Timer = 1;
config.Name = this.GetType().Name;
try
{
if (string.IsNullOrEmpty(configPath))
{
//默認(rèn)各個dllXml配置
var defaultConfigFolder = "PluginXml";
var baseAddr = Directory.GetCurrentDirectory();
configPath = Path.Combine(baseAddr, defaultConfigFolder, config.Name + ".xml");
}
var doc = XDocument.Load(configPath);
config.doc = doc;
var taskMain = doc.Root;
config.Timer = Convert.ToInt32(taskMain.Element(XName.Get("Timer", "")).Value);
config.Name = taskMain.Element(XName.Get("Name", "")).Value;
config.Des = taskMain.Element(XName.Get("Des", "")).Value;
config.UserName = taskMain.Element(XName.Get("UserName", "")).Value;
config.UserPwd = taskMain.Element(XName.Get("UserPwd", "")).Value;
config.ApiKey = taskMain.Element(XName.Get("ApiKey", "")).Value;
config.ApiUrl = taskMain.Element(XName.Get("ApiUrl", "")).Value;
config.CloseTask = taskMain.Element(XName.Get("CloseTask", "")).Value == "1";
}
catch (Exception ex)
{
config.TpError = ex.Message;
PublicClass._WriteLog($"{config.Name}初始化配置信息異常:{ex.Message}", "BaseLog");
throw new Exception(ex.Message);
}
return config;
}
#endregion
#region 初始化-開始加載 _Load
/// <summary>
/// 初始化-開始起
/// </summary>
public virtual void TPlugin_Load()
{
PublicClass._WriteLog("測試");
}
#endregion
#region 釋放資源
public void Dispose()
{
GC.SuppressFinalize(this);//不需要再調(diào)用本對象的Finalize方法
}
public virtual void Dispose(Action action)
{
action();
}
#endregion
}
#region 配置文件 XmlConfig
public class XmlConfig
{
public XmlConfig()
{
}
/// <summary>
/// 定制器時間(分鐘)
/// </summary>
public int Timer { get; set; }
/// <summary>
/// 運行名稱
/// </summary>
public string Name { get; set; }
/// <summary>
/// 描述(第一次獲取dll描述,后面獲取xml配置文件描述)
/// </summary>
public string Des { get; set; }
/// <summary>
/// 接口賬號
/// </summary>
public string UserName { get; set; }
/// <summary>
/// 接口密碼
/// </summary>
public string UserPwd { get; set; }
/// <summary>
/// 接口秘鑰
/// </summary>
public string ApiKey { get; set; }
/// <summary>
/// 接口地址
/// </summary>
public string ApiUrl { get; set; }
/// <summary>
/// 是否關(guān)閉任務(wù)
/// </summary>
public bool CloseTask { get; set; }
/// <summary>
/// 插件中錯誤
/// </summary>
public string TpError { get; set; }
/// <summary>
/// xml信息
/// </summary>
public XDocument doc { get; set; }
}
#endregion
}
具體的說明和邏輯處理代碼中都有注釋,各位可以詳細(xì)看下;這里要訴說的是該框架主要原理是動態(tài)加載任務(wù)dll來創(chuàng)建對象,netcore的程序集類Assembly不像framework里面的Assembly一樣那么多可以用方法,我這里用的Assembly.Load(),netcore只能加載當(dāng)前系統(tǒng)根目錄的dll(這里我花了幾個小時測試,有不同結(jié)果的朋友,請及時聯(lián)系我謝謝),框架使用Task.Run()方法創(chuàng)建不同任務(wù),實現(xiàn)并行執(zhí)行的效果,并且各個容易出錯地方使用try...catch來容錯,避免了某個子任務(wù)異常后,導(dǎo)致框架全部中斷運行,個人覺得其實還是不錯的是吧;
下面給出幾個不同環(huán)境下的壓縮包,以供使用和參考:
TaskCore.MainForm-純文件 TaskCore.MainForm01 git源碼地址
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
.NET的file文件上傳控件使用方法 修改web.config文件上傳大文件
這篇文章主要介紹了.NET修改web.config文件上傳大文件的方法,大家參考使用吧2014-01-01
Asp.net中使用PageDataSource分頁實現(xiàn)代碼
這篇文章主要介紹asp.net中使用PageDataSource分頁的方法,需要的朋友可以參考下2013-04-04
asp.net開發(fā)sql server轉(zhuǎn)換成oracle的方法詳解
這篇文章主要給大家介紹了關(guān)于asp.net開發(fā)中sql server轉(zhuǎn)換成oracle的相關(guān)資料,文中通過示例代碼和圖文將實現(xiàn)的步驟一步步介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧。2017-08-08
一步步打造簡單的MVC電商網(wǎng)站BooksStore(4)
這篇文章主要和大家一起一步步打造一個簡單的MVC電商網(wǎng)站,MVC電商網(wǎng)站BooksStore第四篇,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-04-04
ABP引入SqlSugar框架的簡單版創(chuàng)建使用
這篇文章主要為大家介紹了ABP引入SqlSugar框架的簡單版創(chuàng)建使用,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-04-04

