Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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#_Multithreading_Task - Fatal编程技术网

C# 从线程计时器启动的任务

C# 从线程计时器启动的任务,c#,multithreading,task,C#,Multithreading,Task,*编辑:请参阅下面我的答案以了解解决方案 以下情况是否有危险?我正试图找出我认为可能是比赛的情况。我想我应该从这里开始,然后从那里开始 private BlockingCollection<MyTaskType>_MainQ = new BlockingCollection<MyTaskType>(); private void Start() { _CheckTask = new Timer(new TimerCallback(CheckTasks), null,

*编辑:请参阅下面我的答案以了解解决方案

以下情况是否有危险?我正试图找出我认为可能是比赛的情况。我想我应该从这里开始,然后从那里开始

private BlockingCollection<MyTaskType>_MainQ = new BlockingCollection<MyTaskType>();
private void Start()
{
  _CheckTask = new Timer(new TimerCallback(CheckTasks), null, 10, 5000);
}

private void CheckTasks(object state)
{
  _CheckTask.Change(Timeout.Infinite, Timeout.Infinite);
  GetTask();
  _CheckTask.Change(5000,5000);
}

private void GetTask()
{
  //get task from database to object
  Task.Factory.StartNew( delegate {
    AddToWorkQueue(); //this adds to _MainQ which is a BlockingCollection
  });
}

private void AddToWorkQueue()
{
  //do some stuff to get stuff to move
  _MainQ.Add(dataobject);
}

您认为从
FastSql.ExecuteDataTable
返回值可能会有问题吗?因为它是一个静态类,然后使用
块将其与
一起使用?

我个人会小心在很多地方引入额外的线程-“这里是龙”在处理线程时是一条有用的规则!我看不出你有什么问题,但如果简单一点,就更容易确定了。我假设您希望在不同的线程中完成对“AddToWorkQueue”的调用(以测试竞争条件),因此我将其保留在了中

这能满足你的需要吗?(因此可能是错误的)


随机搁置-首选“throw;”而不是“throw ex;”-前者保留原始调用堆栈,后者只提供“throw ex;”调用的行号。更好的是,在本例中省略try/catch,因为您所做的只是重新抛出异常,因此您还可以节省尝试的开销。

事实证明,这个问题非常非常奇怪


我将原始解决方案从.NET3.5解决方案转换为.NET4.0解决方案。当我在全新的.NET4.0解决方案中重新创建整个解决方案时,锁定问题就消失了。没有引入其他更改,因此我非常确信问题在于升级到4.0。

是的,基本上这是正确的。不过,我更愿意使用Threading.Timer回调,因为它比while(true){sleep}在CPU上更高效、更容易。这里有几个线程提到了这一点。你能在队列中发布一段调用
Take
的代码吗?另外,显示调用
ExecuteNonQuery
的时间也会很有用。我真的很想看到显示执行哪个线程的代码。我假设调用
Take
的线程是同一个线程。如果是这种情况,那么您在这里至少有3个线程1)调用
Add
2)计时器回调本身3)和调用
Take
的线程。完整了解线程如何交互是识别任何可能的争用条件的唯一可靠方法。不,我认为这与
FastSql.ExecuteDataTable的返回无关。ExecuteDataTable
是使用
的目标。我仍然不知道在哪里调用了
BlockingCollection.Take
方法。
public static void ExecuteNonQuery(string connectionString, string sql, CommandType commandType, List<FastSqlParam> paramCollection = null, int timeout = 60)
{
  //Console.WriteLine("{0} [Thread {1}] called ExecuteNonQuery", DateTime.Now.ToString("HH:mm:ss:ffffff"), System.Threading.Thread.CurrentThread.ManagedThreadId);
  using (SqlConnection connection = new SqlConnection(connectionString))
  using (SqlCommand command = new SqlCommand(sql, connection))
  {
    try
    {
      if (paramCollection != null)
      {
        foreach (FastSqlParam fsqlParam in paramCollection)
        {
          try
          {
            SqlParameter param = new SqlParameter();
            param.Direction = fsqlParam.ParamDirection;
            param.Value = fsqlParam.ParamValue;
            param.ParameterName = fsqlParam.ParamName;
            param.SqlDbType = fsqlParam.ParamType;
            command.Parameters.Add(param);
          }
          catch (ArgumentNullException anx)
          {
            throw new Exception("Parameter value was null", anx);
          }
          catch (InvalidCastException icx)
          {
            throw new Exception("Could not cast parameter value", icx);
          }
        }
      }

      connection.Open();
      command.CommandType = commandType;
      command.CommandTimeout = timeout;
      command.ExecuteNonQuery();

      if (paramCollection != null)
      {
        foreach (FastSqlParam fsqlParam in paramCollection)
        {
          if (fsqlParam.ParamDirection == ParameterDirection.InputOutput || fsqlParam.ParamDirection == ParameterDirection.Output)
            try
            {
              fsqlParam.ParamValue = command.Parameters[fsqlParam.ParamName].Value;
            }
            catch (ArgumentNullException anx)
            {
              throw new Exception("Output parameter value was null", anx);
            }
            catch (InvalidCastException icx)
            {
              throw new Exception("Could not cast parameter value", icx);
            }
        }
      }
    }
    catch (SqlException ex)
    {
      throw ex;
    }
    catch (ArgumentException ex)
    {
      throw ex;
    }
  }
}
FastSql.ExecuteNonQuery(connectionString, "someProc", System.Data.CommandType.StoredProcedure, new List<FastSqlParam>() { new FastSqlParam(SqlDbType.Int, "@SomeParam", variable)});
//Called from Thread A
void ProcessTask()
{
    var parameters = new List<FastSqlParam>() { new FastSqlParam(SqlDbType.Int, "@SomeParam", variable) };
    using (DataTable someTable = FastSql.ExecuteDataTable(connectionString, "someProc", CommandType.StoredProcedure, parameters))
    {
        SomeTask task = new Task();

            //assign task some data from dt.Rows[0]

            if (task != null)
            {
                Task.Factory.StartNew(delegate { AddFilesToQueue(task); });
            }
        }
    }

void AddFilesToQueue(Task task)
{
    //connect to remote system and build collection of files to WorkItem
    //e.g, WorkItem will have a collection of collections to transfer.  We control this throttling mechanism to allow more threads to split up the work
    _MainQ.Add(WorkItem);
}

while(true) {
    Task.Factory.StartNew( delegate { AddToWorkQueue(); });
    Thread.Sleep(5000);
}