Ошибка автоматизации 80004005 - PullRequest
1 голос
/ 25 сентября 2011

Я избивал себя этим уже несколько дней, искал в интернете. Я знаю, что многое из того, что я не совсем понимаю в Com Interop, но мне удалось построить и использовать более простые библиотеки DLL в Excel. В любом случае в точку.

Я получаю вышеупомянутую ошибку -2147467259 80004005 Automation Error Unspecified Error в Excel VBA при запуске следующего кода, заключенного в DLL.

[GuidAttribute("96BE21CD-887B-4770-9FAA-CF395375AEA9")]
[ComVisibleAttribute(true)]
interface QInterface
{
    void ConnectionFill(string SQLQuery, string CONStr);
    string QueryValue(int QueryKey);
    string ConnectionValue(int ConnectionKey);
    string outputFile { get; set; }
    void ThreadTest();
}
[ClassInterfaceAttribute(ClassInterfaceType.None)]
[ProgIdAttribute("QueryThread")]
class QueryThread : QInterface
{
    DataSet QueryReturn = new DataSet();
    private ArrayList SQLList = new ArrayList();
    private ArrayList ConList = new ArrayList();
    private string OutputFile;


    public void ConnectionFill(string SQLQuery, string CONStr)
    {
        SQLList.Add(SQLQuery);
        ConList.Add(CONStr);
    }

    public string QueryValue(int QueryKey)
    {
        return SQLList[QueryKey].ToString();
    }

    public string ConnectionValue(int ConnectionKey)
    {
        return ConList[ConnectionKey].ToString();
    }


    public string outputFile
    {
        set { OutputFile = value; }
        get { return OutputFile; }
    }

    public void ThreadTest()
    {
        int i = 0;

        i = SQLList.Count;
        Thread[] myThreads;
        myThreads = new Thread[i];
        for (int t = 0; t != i; t++)
        {

            myThreads[t] = new Thread(() => ThreadRun(SQLList[t].ToString(), ConList[t].ToString()));
            myThreads[t].Name = "Thread " + t;
            myThreads[t].IsBackground = true;
            myThreads[t].Start();
            Thread.Sleep(600);
            if (t > 9)
            {
                myThreads[t - 9].Join();
            }
        }

        for (int t = 0; t != i; t++)
        {
            while (myThreads[t].IsAlive)
            {
                Thread.Sleep(20);
            }
        }

        TextWriter tw = new StreamWriter(OutputFile);
        for (int t = 0; t < QueryReturn.Tables.Count; t++)
        {
            DataTableReader DR = QueryReturn.Tables[t].CreateDataReader();
            while (DR.Read())
            {
                tw.WriteLine("{0} : {1}", DR.GetValue(0), DR.GetValue(1));
            }
        }
        tw.Close();
        QueryReturn.Dispose();
    }

    private void ThreadRun(string SQLString, string ConString)
    {
        try
        {
            OleDbConnection DBCon = new OleDbConnection(ConString);
            DBCon.Open();
            Thread.Sleep(200);
            OleDbCommand DBCmd = new OleDbCommand(SQLString, DBCon);
            OleDbDataAdapter DataAdapter = new OleDbDataAdapter(DBCmd);
            Thread.Sleep(200);
            DataAdapter.Fill(QueryReturn, Thread.CurrentThread.Name.ToString());
            DBCon.Close();
            DataAdapter.Dispose();
            DBCon.Dispose();
            DBCmd.Dispose();
        }
        finally
        {
        }
    }
}

используя этот код VBA ...

Sub test()

    Dim QT As New QueryThreading.QueryThread
    Dim MyResults As String
    Dim outputfile As String
    Dim InputStuff(1, 1) As String

    InputStuff(0, 0) = "Select DISTINCT * From TrackingData;"
    InputStuff(0, 1) = "Provider =Microsoft.ACE.OLEDB.12.0;Data Source =C:\Users\Nick\Desktop\test.accdb; Persist Security Info =False;Connection Timeout=7;"
    InputStuff(1, 0) = "Select DISTINCT * From TrackingData;"
    InputStuff(1, 1) = "Provider =Microsoft.ACE.OLEDB.12.0;Data Source =C:\Users\Nick\Desktop\test2.accdb; Persist Security Info =False;Connection Timeout=7;"


    QT.ConnectionFill InputStuff(0, 0), InputStuff(0, 1)
    QT.ConnectionFill InputStuff(1, 0), InputStuff(1, 1)
    outputfile = "C:\Users\Nick\Desktop\testrun.txt"
    QT.outputfile = outputfile
    QT.ThreadTest
End Sub

Работает нормально - консольное приложение на чистом C #. Работает отлично и быстро без проблем. Но через VBA я получаю ошибку.

Я предполагаю, что это как-то связано с вызовом баз данных доступа в нескольких потоках. Я знаю, что там много мусорного кода, он не оптимизирован, конечно, я все еще в фазе "игры вокруг".

Я использовал RegAsm и включил com-взаимодействие и все такое, я могу читать из возвратов просто отлично. Так что я знаю, что DLL работает правильно, просто когда я заполняю потоки и запускаю «ThreadTest ()», я получаю ошибку автоматизации.

Если я запускаю его во второй раз, Excel блокируется.

Любая помощь будет принята с благодарностью.

1 Ответ

0 голосов
/ 25 сентября 2011

Вы звоните QT.DictionaryFill, хотя я не могу найти соответствующий метод в вашем коде C # ... что произойдет, если вы измените вызов на QT.ConnectionFill вместо?

Еще один момент: IIRCзатем VBA запускает объект в STA - не уверен, поддерживается ли MTA, хотя

EDIT:

Согласно этот довольно старый пост VBA не поддерживает многопоточность ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...