【发布时间】:2016-05-18 22:55:38
【问题描述】:
我需要一个监视文件夹过程的无限循环。我让它通过数据表每 30 秒执行一次 Parallel.ForEach(iterate.AsEnumerable(), drow => 方法。但是,使用 while(true) 循环似乎会导致我出现 stackoverflow 异常。
我想知道是否有更好的方法来实现无限循环,可以帮助我消除异常。
更新 1
从 SQL 数据库中填充数据表,并以 Windows 形式向用户展示。数据表具有用户可以编辑的监视文件夹位置。这就是我正在迭代的内容。这些文件夹是通过 SOAP Web 服务访问的。
这是代码 - 抱歉,它很长,但我认为你们都需要查看所有代码以了解上下文。如果您需要进一步说明,请告诉我。
这会通过单击按钮开始该过程
public partial class HomePage : Form
{
public void button1_Click(object sender, EventArgs e)
{
//set serviceStop to 0 (false)
string connectionString = @"Data Source=FCMONITOR\AVIDAUTO;Initial Catalog=InterplayWatchFolder;Integrated Security=True";
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlCommand setCancelRequest = new SqlCommand("UPDATE SERVICE_STOP SET SERVICE_STOP_REQUESTED = 0");
setCancelRequest.CommandType = CommandType.Text;
setCancelRequest.Connection = connection;
connection.Open();
setCancelRequest.ExecuteNonQuery();
connection.Close();
}
//start service
initiateThread();
}
private void initiateThread()
{
Console.WriteLine("Initiating new check");
System.Threading.Tasks.Task newJobTask = System.Threading.Tasks.Task.Factory.StartNew(() =>
{
repeater();
}
private void repeater()
{
while(true)
{
string serviceStop = "False";
//check if service stop was requested
string connectionString = @"Data Source=FCMONITOR\AVIDAUTO;Initial Catalog=InterplayWatchFolder;Integrated Security=True";
using (SqlConnection connection = new SqlConnection(connectionString))
{
SqlDataReader stopServiceRequestedReader = null;
SqlCommand getStopServiceRequested = new SqlCommand("SELECT [SERVICE_STOP_REQUESTED] FROM SERVICE_STOP", connection);
getStopServiceRequested.CommandType = CommandType.Text;
connection.Open();
stopServiceRequestedReader = getStopServiceRequested.ExecuteReader();
while (stopServiceRequestedReader.Read())
{
serviceStop = stopServiceRequestedReader["SERVICE_STOP_REQUESTED"].ToString();
}
connection.Close();
}
//check if service was stopped
if (serviceStop == "False")
{
Thread.Sleep(30000);
System.Threading.Tasks.Task newJobTask = System.Threading.Tasks.Task.Factory.StartNew(() =>
{
executeThreadRunService();
garbage garbage = new garbage();
garbage.Dispose();
}
);
}
else
{
garbage garbage = new garbage();
garbage.Dispose();
break;
Thread.CurrentThread.Join();
}
}
private void executeThreadRunService()
{
{
//iterate workflow across table
DataTable iterate = (DataTable)interplaySetupView.DataSource;
//execute service in parallel
{
Parallel.ForEach(iterate.AsEnumerable(), drow =>
{
//Set Variables
string insertDeliniator = "/"; //extra needed to build URI
string insertInterplay = "interplay://"; //extra info needed to build URI
string interplayEngineHostname = drow["Interplay_Engine_Hostname"].ToString();
string interplayWatchFolder = insertInterplay + drow["Interplay_Engine_Hostname"].ToString() + insertDeliniator + drow["Interplay_Watch_Folder"].ToString();
string safeForTranscodingFolder = insertInterplay + drow["Interplay_Engine_Hostname"].ToString() + insertDeliniator + drow["Interplay_Safe_Folder"].ToString();
string safeForTranscodingSubmitURI = "interplay://Interplay/" + drow["Interplay_Safe_Folder"].ToString();
string transferEngineHostname = drow["Transfer_Engine_Hostname"].ToString();
string transferPlaybackDevice = drow["Transfer_Profile"].ToString();
string transcodingProfile = drow["Transcoding_Profile"].ToString();
string storeInterplayUsername = interplayUsername.Text.ToString();
string storeInterplayPassword = interplayPasswordInput.Text.ToString();
string workflowName = drow["Workflow_Name"].ToString();
string catDVEnabled = drow["CATDV_ENABLED"].ToString();
string catDVXMLDumpLocation = drow["CATDV_XML_DUMP_LOCATION"].ToString();
string xmlMetadataDumpLocation = drow["METADATA_XML_DUMP_LOCATION"].ToString();
string rewriteSequenceMetadata = drow["REWRITE_SEQUENCE_METADATA"].ToString();
System.Threading.Tasks.Task newWatchTask = System.Threading.Tasks.Task.Factory.StartNew
(
() =>
runService.executeWatchService
(
interplayEngineHostname,
interplayWatchFolder,
safeForTranscodingFolder,
safeForTranscodingSubmitURI,
transcodingProfile,
transferEngineHostname,
transferPlaybackDevice,
interplayUsernameInput.Text.ToString(),
interplayPasswordInput.Text.ToString(),
workflowName,
catDVEnabled,
catDVXMLDumpLocation,
xmlMetadataDumpLocation,
rewriteSequenceMetadata
) );
garbage garbage = new garbage();
garbage.Dispose();
Thread.CurrentThread.Join();
}
}
//another class where the runService method is
public class runService
{
public static void executeWatchService(
string interplayEngineHostname,
string interplayWatchFolder,
string safeForTranscodingFolder,
string safeForTranscodingSubmitURI,
string transcodingProfile,
string transferEngineHostname,
string transferPlaybackDevice,
string interplayUsername,
string interplayPassword,
string workflowName,
string catDVEnabled,
string catDVXMLDumpLocation,
string xmlMetadataDumpLocation,
string rewriteSequenceMetadata
)
{
{
{
//Find if there is a new sequence
//If none, method exits
WatchForNewSequence watchForNewSequence = new WatchForNewSequence();
WatchForNewSequence.returnMOBIDandJobName MOBIDandJobNameResults = watchForNewSequence.searchForNewSequence(
interplayWatchFolder,
interplayUsername,
interplayPassword,
workflowName,
safeForTranscodingFolder);
string returnOriginalSequenceMOBID = MOBIDandJobNameResults.returnOriginalSequenceMOBID;
string returnJobName = MOBIDandJobNameResults.returnJobName;
//another class where the WatchForNewSequence method is
class WatchForNewSequence
{
public struct returnMOBIDandJobName
{
public string returnOriginalSequenceMOBID;
public string returnJobName;
}
public returnMOBIDandJobName searchForNewSequence(
string interplayWatchFolder,
string interplayUsername,
string interplayPassword,
string workflowName,
string safeForTranscodingFolder
)
{
string originalSequenceMOBID = "empty";
string jobName = "empty";
Console.WriteLine("Checking for new sequence for " + interplayWatchFolder);
AssetsPortTypeClient port = new AssetsPortTypeClient();
UserCredentialsType creds = new UserCredentialsType();
creds.Username = interplayUsername;
creds.Password = interplayPassword;
//parameters currenlty set for sequences only
//masterclip do not send in this verison
SearchType param = new SearchType();
param.MaxResults = 1;
param.InterplayPathURI = interplayWatchFolder;
param.SearchGroup = new SearchGroupType();
param.SearchGroup.Operator = "AND";
param.SearchGroup.AttributeCondition = new AttributeConditionType[1];
param.SearchGroup.AttributeCondition[0] = new AttributeConditionType();
param.SearchGroup.AttributeCondition[0].Condition = "EQUALS";
param.SearchGroup.AttributeCondition[0].Attribute = new AttributeType();
param.SearchGroup.AttributeCondition[0].Attribute.Name = "Type";
param.SearchGroup.AttributeCondition[0].Attribute.Group = "SYSTEM";
param.SearchGroup.AttributeCondition[0].Attribute.Value = "sequence";
//send request
SearchRequest request = new SearchRequest();
request.UserCredentials = creds;
request.Search = param;
garbage garbage = new garbage();
garbage.Dispose();
GC.Collect();
GC.WaitForFullGCComplete();
SearchResponseType response = port.Search(creds, param);
//check if there is any sequences
if (response.Results.Length > 0)
{
//designate that we want the MOB ID to be returned as a result of this method
foreach (AssetDescriptionType ad in response.Results)
{
foreach (AttributeType att in ad.Attributes)
{
if (att.Name == "MOB ID")
{
originalSequenceMOBID = att.Value;
}
if (att.Name == "Display Name")
{
jobName = att.Value;
//The original sequence MOBID is found and returned from the WatchForNewSequence Class
Console.WriteLine(originalSequenceMOBID + "...." + jobName);
}
garbage garbage2 = new garbage();
garbage.Dispose();
}
}
}
else
{
originalSequenceMOBID = "No_Sequence";
Console.WriteLine("No new sequence for " + interplayWatchFolder + " -- exiting");
garbage garbage3 = new garbage();
garbage.Dispose();
Thread.CurrentThread.Join();
}
//no new sequence, methods exit and program ends
if (response.Errors != null)
{
foreach (ErrorType watchForNewSequenceError in response.Errors)
{
Console.WriteLine("ERROR: " + watchForNewSequenceError.Message + watchForNewSequenceError.Details + "at" + watchForNewSequenceError.InterplayURI);
}
}
returnMOBIDandJobName returnMOBIDandJobName = new returnMOBIDandJobName();
returnMOBIDandJobName.returnOriginalSequenceMOBID = originalSequenceMOBID;
returnMOBIDandJobName.returnJobName = jobName;
return returnMOBIDandJobName;
//return originalSequenceMOBID to Program
//return originalSequenceMOBID;
}
}
【问题讨论】:
-
您必须提供相关代码。
while(true) {}本身没有问题 -
在
while(true)循环中的某个地方,您可能正在调用该方法本身,当然您会一次又一次地调用该方法,而不会离开它,这会导致 stackoverflow 异常。 -
也许你的
while(true)中的代码不是线程安全的? -
查看quartz.net 或hangfire
-
通常的做法是发布尽可能少的代码来复制您的问题。您刚刚将整个课程倾倒到问题中,它甚至没有编译。
标签: c# stack-overflow