作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用用于证件扫描器的外部库,为简单起见,我将其称为ScanLib。扫描过程很长,当然,在调用诸如ScanLib.Scan()之类的方法时,它往往会阻塞UI线程,因此我认为这是使用Tasks的绝佳时机。这里是用于上下文的简化(或TLDR)代码(下面的完整代码以获取更多详细信息,但为了节省时间,此处进行了总结):
public partial class MainForm : Form ()
{
//Here I initialize the reference variable which I will use to work with the Scanner library
ScanLib scanLibraryReference = new ScanLib();
// Form constructor
public Form()
{
//This initializes the scanner and it's library components, it runs until the program closes
Task scannerInitTask = Task.Run(() => scanLibraryReference.InitializeScanLibrary())
InitializeComponent();
}
private void Button_Click(object sender, EventArgs e) {
Task scannerTask = Task.Run(() => scanLibraryReference.ScanCard());
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using ScannerTest;
using System.Threading;
namespace ScannerTest
{
public partial class Form1 : Form
{
// All 4 variables below are global and used extensively to call scanner methods
// Main Scan basic functions Library
NetScanW.SLibEx scanSlibxEx = new NetScanW.SLibEx();
// Main Scan extended functios Library
NetScanW.CImage scanCImage = new NetScanW.CImage();
// Main Scan OCR functions library
NetScanW.IdData scanIdData = new NetScanW.IdData();
// Main Scan extended functions 2 library
NetScanWex.SLibEx scanWexSlibxEx = new NetScanWex.SLibEx();
string ImageSource = @"C:\Scans\";
public Form1()
{
Task initTask = Task.Run(() => InitScanLibraries());
InitializeComponent();
Console.WriteLine("\nForm initialized succesfully.");
}
#region Button events
// The normal way of scanning which of course blocks the main UI thread
private void ScanCardNonAsync_Click(object sender, EventArgs e)
{
Console.WriteLine("");
Console.WriteLine("*********************");
Console.WriteLine("Starting new scan...");
string currentScan = ImageSource + "MyScan.bmp";
string modifiedScan = ImageSource + "MyEditedScan.bmp";
ScanCard(currentScan, modifiedScan);
OCRscan();
GetOCRData();
Console.WriteLine("Scan finalized..");
Console.WriteLine("*********************");
}
// My attempt at scanning asynchronously which still blocks the UI thread
private void ScanCardAsync_Click(object sender, EventArgs e)
{
Console.WriteLine("");
Console.WriteLine("*********************");
Console.WriteLine("Starting new scan...");
string currentScan = ImageSource + "MyScan.bmp";
string modifiedScan = ImageSource + "MyEditedScan.bmp";
// Here I chain the methods in a task chain to scan a Card
Task ScannerStart = new Task(() => ScanCard(currentScan, modifiedScan));
Task ScannerStep2 = ScannerStart.ContinueWith((x) => OCRscan());
Task ScannerStep3 = ScannerStep2.ContinueWith((y) => GetOCRData());
ScannerStart.Start();
}
#endregion
#region Methods
private void InitScanLibraries()
{
switch (scanSlibxEx.InitLibrary("49B2MFWE8WUJXLBW"))
{
case SLIB_ERR_SCANNER_BUSSY:
System.Console.WriteLine("ERROR: Scanner Busy...");
break;
case LICENSE_VALID:
System.Console.WriteLine("");
System.Console.WriteLine("**********************************");
System.Console.WriteLine("SlibxEx initialized succesfully...");
break;
case LICENSE_INVALID:
System.Console.WriteLine("ERROR: License Invalid");
break;
case LICENSE_EXPIRED:
System.Console.WriteLine("ERROR: License Expired");
break;
case SLIB_ERR_DRIVER_NOT_FOUND:
System.Console.WriteLine("ERROR: Driver not found");
break;
case SLIB_ERR_SCANNER_NOT_FOUND:
System.Console.WriteLine("ERROR: Scanner not found");
break;
}
switch (scanIdData.InitLibrary("49B2MFWE8WUJXLBW"))
{
case SLIB_ERR_SCANNER_BUSSY:
System.Console.WriteLine("ERROR: Scanner Busy...");
break;
case LICENSE_VALID:
System.Console.WriteLine("License validation succesful...");
break;
case LICENSE_INVALID:
System.Console.WriteLine("ERROR: License Invalid");
break;
case LICENSE_EXPIRED:
System.Console.WriteLine("ERROR: License Expired");
break;
case SLIB_ERR_DRIVER_NOT_FOUND:
System.Console.WriteLine("ERROR: Driver not found");
break;
case SLIB_ERR_SCANNER_NOT_FOUND:
System.Console.WriteLine("ERROR: Scanner not found");
break;
case GENERAL_ERR_PLUG_NOT_FOUND:
System.Console.WriteLine("ERROR: Attatched scanner is not one of the following:\n ScanShell 600 \n ScanShell 800 \n ScanShell1000");
break;
case SLIB_LIBRARY_ALREADY_INITIALIZED:
System.Console.WriteLine("ERROR: Call ignored, library already initialized");
break;
}
}
private void ScanCard(string ImagePath, string ModifiedImagePath)
{
Console.WriteLine("Attempting scan...");
switch (scanSlibxEx.ScanToFile(ImagePath))
{
case SLIB_ERR_NONE:
Console.WriteLine("Scan succesful...");
break;
case SLIB_ERR_SCANNER_BUSSY:
Console.WriteLine("ERROR: Scanner is busy...");
break;
case LICENSE_INVALID:
Console.WriteLine("ERROR: License invalid");
break;
case SLIB_ERR_SCANNER_NOT_FOUND:
Console.WriteLine("ERROR: Scanner not found");
break;
case SLIB_ERR_SCANNER_GENERAL_FAIL:
Console.WriteLine("ERROR: Scanner general fail");
break;
case SLIB_ERR_HARDWARE_ERROR:
Console.WriteLine("ERROR: Hardware error");
break;
case SLIB_ERR_PAPER_FED_ERROR:
Console.WriteLine("ERROR: Paper fed error");
break;
case SLIB_ERR_SCANABORT:
Console.WriteLine("ERROR: Scan aborted");
break;
case SLIB_ERR_NO_PAPER:
Console.WriteLine("ERROR: No paper");
break;
case SLIB_ERR_PAPER_JAM:
Console.WriteLine("ERROR: Paper jammed");
break;
case SLIB_ERR_FILE_IO_ERROR:
Console.WriteLine("ERROR: File I/O error");
break;
case SLIB_ERR_PRINTER_PORT_USED:
Console.WriteLine("ERROR: Printer port used");
break;
case SLIB_ERR_OUT_OF_MEMORY:
Console.WriteLine("ERROR: Out of memory");
break;
}
//scanCImage.RotateImage(ImageSource, 90, 1, ModifiedImagePath);
}
private void OCRscan()
{
Console.WriteLine("Attempting OCR extraction...");
string data = "";
int region = scanIdData.AutoDetectState(data);
// Check for card region
switch (region)
{
case ID_ERR_USA_TEMPLATES_NOT_FOUND:
Console.WriteLine("ERROR: No USA templates found");
break;
case INVALID_INTERNAL_IMAGE:
Console.WriteLine("ERROR: No internal image loaded");
break;
case ID_ERR_STATE_NOT_SUPORTED:
Console.WriteLine("ERROR: State not supported");
break;
case ID_ERR_STATE_NOT_RECOGNIZED:
Console.WriteLine("ERROR: State not recognized");
break;
default:
Console.WriteLine("Region catch succesful");
break;
}
// Begin OCR extraction
string data2 = "";
Console.WriteLine("Attempting data extraction...");
switch (scanIdData.ProcState(data2, region))
{
case ID_TRUE:
Console.WriteLine("Data extraction succesful.");
break;
case LICENSE_INVALID:
Console.WriteLine("ERROR: LICENSE_INVALID");
break;
case SLIB_ERR_SCANNER_NOT_FOUND:
Console.WriteLine("ERROR: SLIB_ERR_SCANNER_NOT_FOUND. ");
break;
case SLIB_ERR_INVALID_SCANNER:
Console.WriteLine("ERROR: SLIB_ERR_INVALID_SCANNER. ");
break;
case ID_ERR_STATE_NOT_SUPORTED:
Console.WriteLine("ERROR: ID_ERR_STATE_NOT_SUPORTED. ");
break;
case INVALID_INTERNAL_IMAGE:
Console.WriteLine("ERROR: INVALID_INTERNAL_IMAGE. ");
break;
default:
Console.WriteLine("ERROR: Uncatched exception in Form1.OCRScan()");
break;
}
// Data copying to local
Console.WriteLine("Copying data locally...");
if (scanIdData.RefreshData() != 0) Console.WriteLine("Data copied succesfully."); else Console.WriteLine("ERROR: Problem while copying data");
}
private void GetOCRData()
{
//loc* Variables are locally declared global variables, while the scanIdData.* are library variables where OCR scan results are saved
Console.WriteLine("Saving data locally...");
locName = scanIdData.Name;
locNameFirst = scanIdData.NameFirst;
locNameMiddle = scanIdData.NameMiddle;
locNameLast = scanIdData.NameLast;
locNameSuffix = scanIdData.NameSuffix;
locID = scanIdData.Id;
locLicense = scanIdData.license;
locIssueDate = scanIdData.IssueDate;
locAddress = scanIdData.Address;
locExperationDate = scanIdData.ExpirationDate;
locCSC = scanIdData.CSC;
locCity = scanIdData.City;
locEyes = scanIdData.Eyes;
locDup_Test = scanIdData.Dup_Test;
locState = scanIdData.State;
locHair = scanIdData.Hair;
locEndorsements = scanIdData.Endorsements;
locZip = scanIdData.Zip;
locHeight = scanIdData.Height;
locFee = scanIdData.Fee;
locCounty = scanIdData.County;
locClass = scanIdData.Class;
locRestriction = scanIdData.Restriction;
locDateOfBirth = scanIdData.DateOfBirth;
locSex = scanIdData.Sex;
locSigNum = scanIdData.SigNum;
locType = scanIdData.Type;
locWeight = scanIdData.Weight;
locAddress2 = scanIdData.Address2;
locAddress3 = scanIdData.Address3;
locAddress4 = scanIdData.Address4;
locAddress5 = scanIdData.Address5;
locText1 = scanIdData.Text1;
locText2 = scanIdData.Text2;
locText3 = scanIdData.Text3;
Console.WriteLine("Data saved succesfully.");
}
#endregion
}
}
Task debugTask = Task.Run(() =>
{
// All 4 variables below are global and used extensively to call scanner methods
// Main Scan basic functions Library
NetScanW.SLibEx scanSlibxEx = new NetScanW.SLibEx();
// Main Scan extended functios Library
NetScanW.CImage scanCImage = new NetScanW.CImage();
// Main Scan OCR functions library
NetScanW.IdData scanIdData = new NetScanW.IdData();
// Main Scan extended functions 2 library
NetScanWex.SLibEx scanWexSlibxEx = new NetScanWex.SLibEx();
string ImageSource = @"C:\Scans\";
string currentScan = ImageSource + "MyScan.bmp";
string modifiedScan = ImageSource + "MyEditedScan.bmp";
InitScanLibraries(scanSlibxEx, scanIdData);
ScanCard(currentScan, modifiedScan, scanSlibxEx);
});
public void InitializeVariables()
{
NetScanW.SLibEx scanSLibExx = null;
NetScanW.IdData scanIdDataa = null;
NetScanW.CImage scanCImagee = null;
NetScanWex.SLibEx scanWexSLibExx = null;
var th = new Thread(() =>
{
scanSLibExx = new NetScanW.SLibEx();
scanIdDataa = new NetScanW.IdData();
scanCImagee = new NetScanW.CImage();
scanWexSLibExx = new NetScanWex.SLibEx();
});
th.SetApartmentState(ApartmentState.MTA);
th.Start();
th.Join();
this.scanSlibxEx = scanSLibExx;
this.scanIdData = scanIdDataa;
this.scanCImage = scanCImagee;
this.scanWexSlibxEx = scanWexSLibExx;
}
最佳答案
在使用COM库时,这在类似情况下对我有用。
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread] // <= I needed to add this attribute
private static void Main()
{
//...
}
}
public partial class MainForm : Form ()
{
// you can call this in the InitializeComponents() for instance
void someMethodInYourFormIERunningOnTheUIThread()
{
ScanLib scanLib = null;
var th = new Thread(() =>
{
scanLib = new ScanLib();
});
th.SetApartmentState(ApartmentState.MTA); // <== this prevented binding the UI thread for some operations
th.Start();
th.Join();
this.scanLibraryReference = scanLib;
}
//...
}
关于c# - 在主线程上使用大型全局对象时,如何不从工作线程中阻止主UI线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25064454/
我是一名优秀的程序员,十分优秀!